Obtenir la valeur du paramètre à partir d'une expression Linq

c# expression-trees linq

Question

J'ai la classe suivante

public class MyClass
{
    public bool Delete(Product product)
    {
        // some code.
    }
}

Maintenant, j'ai une classe d'assistance qui ressemble à ceci

public class MyClass
{
    public bool Delete(Product product)
    {
        // some code.
    }
}

L'idée est d'utiliser ce code quelque part:

public class MyClass
{
    public bool Delete(Product product)
    {
        // some code.
    }
}

Le point sur lequel je suis coincé est de savoir comment extraire les arguments de l'expression elle-même.

J'ai trouvé ça

public class MyClass
{
    public bool Delete(Product product)
    {
        // some code.
    }
}

qui semble être un type d'objet avec un champ "produit" mais je crois qu'il doit y avoir une solution plus simple.

Aucune suggestion.

Mettre à jour

Juste pour clarifier, j'ai modifié mon code en fonction de ce que je veux accomplir. Dans ma vraie application, j'ai déjà une classe qui fait la même chose mais sans arbre d'expression:

public class MyClass
{
    public bool Delete(Product product)
    {
        // some code.
    }
}

La raison principale de mon Helper<T> est de permettre à Compile-Time de vérifier si la signature de la méthode est valide.

Mise à jour 2

C’est ma mise en œuvre actuelle. Existe-t-il un meilleur moyen d’accéder aux valeurs sans utiliser la réflexion?

public class MyClass
{
    public bool Delete(Product product)
    {
        // some code.
    }
}

Réponse acceptée

Cette méthode fonctionne plutôt bien. Il retourne les types d'arguments et les valeurs pour une expression>

    private static KeyValuePair<Type, object>[] ResolveArgs<T>(Expression<Func<T, object>> expression)
    {
        var body = (System.Linq.Expressions.MethodCallExpression)expression.Body;
        var values = new List<KeyValuePair<Type, object>>();

        foreach (var argument in body.Arguments)
        {
            var exp = ResolveMemberExpression(argument);
            var type = argument.Type;

            var value = GetValue(exp);

            values.Add(new KeyValuePair<Type, object>(type, value));
        }

        return values.ToArray();
    }

    public static MemberExpression ResolveMemberExpression(Expression expression)
    {

        if (expression is MemberExpression)
        {
            return (MemberExpression)expression;
        }
        else if (expression is UnaryExpression)
        {
            // if casting is involved, Expression is not x => x.FieldName but x => Convert(x.Fieldname)
            return (MemberExpression)((UnaryExpression)expression).Operand;
        }
        else
        {
            throw new NotSupportedException(expression.ToString());
        }
    }

    private static object GetValue(MemberExpression exp)
    {
        // expression is ConstantExpression or FieldExpression
        if (exp.Expression is ConstantExpression)
        {
            return (((ConstantExpression)exp.Expression).Value)
                    .GetType()
                    .GetField(exp.Member.Name)
                    .GetValue(((ConstantExpression)exp.Expression).Value);    
        }
        else if (exp.Expression is MemberExpression)
        {
            return GetValue((MemberExpression)exp.Expression);
        }
        else
        {
            throw new NotImplementedException();
        }
    }

Réponse populaire

Vous pouvez compiler l'expression d'argument puis l'invoquer pour calculer la valeur:

var values = new List<object>();
foreach(var arg in body.Arguments)
{
    var value = Expression.Lambda(argument).Compile().DynamicInvoke();
    values.Add(value);
}
this.ArgValues = values.ToArray();



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi