ParameterExpression de type 'System.Int32' ne peut pas être utilisé pour le paramètre délégué de type 'System.String'

c# delegates dynamic expression-trees generics

Question

Je crée un setter général en utilisant un arbre d'expression et voici mon code

public Expression<Action<T,string>> GetAction<T>(string fieldName)
{
    ParameterExpression targetExpr = Expression.Parameter(typeof(T), "Target");  
    MemberExpression fieldExpr = Expression.Property(targetExpr, fieldName);    
    ParameterExpression valueExpr = Expression.Parameter(fieldExpr.Type, "value"); 
    UnaryExpression valueCast = (!fieldExpr.Type.IsValueType) 
                              ? Expression.TypeAs(valueExpr, fieldExpr.Type) 
                              : Expression.Convert(valueExpr, fieldExpr.Type);
    BinaryExpression assignExpr = Expression.Assign(fieldExpr, valueCast);    
    return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);
}

Je n'appelle pas .Compile() dans la méthode ci-dessus parce que je veux examiner l'expression qu'il génère.

Et mon objet est

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

}

J'appelle la méthode comme ça

var lastname = GetAction<Person>("FirstName");
var age = GetAction<Person>("Age");

lastname.Compile()(p, "Solutions");
age.Compile()(p, "10");

La raison pour laquelle je passe l'âge en tant que chaîne est que je vais obtenir cette valeur à partir de XML.

Il crée une action pour FirstName sans erreur alors que pour Age il explose.

Une erreur se produit dans cette ligne pour Age :

 return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);

Erreur:

ParameterExpression de type 'System.Int32' ne peut pas être utilisé pour le paramètre délégué de type 'System.String'

Puis-je faire quelque chose avec dynamique ..?

J'espère que quelqu'un aura une solution. Merci

Réponse acceptée

Vous devez appeler Convert.ChangeType pour la conversion de type:

public static Expression<Action<T, string>> GetAction<T>(string fieldName)
{
    ParameterExpression targetExpr = Expression.Parameter(typeof(T), "Target");
    MemberExpression fieldExpr = Expression.Property(targetExpr, fieldName);
    ParameterExpression valueExpr = Expression.Parameter(typeof(string), "value");
    MethodCallExpression convertExpr = Expression.Call(typeof(Convert),
        "ChangeType", null, valueExpr, Expression.Constant(fieldExpr.Type));
    UnaryExpression valueCast = Expression.Convert(convertExpr, fieldExpr.Type);
    BinaryExpression assignExpr = Expression.Assign(fieldExpr, valueCast);
    return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);
}

Réponse populaire

Le problème est le suivant:

Vous retournez une Expression<Action<T,string>> , ce qui signifie que le résultat sera une string . D'autre part, vous transmettez "Age" comme nom du champ que l'action doit renvoyer. Age est cependant de type int , pas de string .

Vous pouvez résoudre ce problème d'au moins deux manières:

  1. Ajoutez un deuxième paramètre générique à votre méthode GetAction qui spécifie le type de retour.
  2. Ajoutez un appel à ToString sur la propriété renvoyée à l'expression.



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