简体   繁体   中英

ParameterExpression of type 'System.Int32' cannot be used for delegate parameter of type 'System.String'

I'm creating a general setter using expression tree and here is my 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);
}

I don't call .Compile() in the above method because I want to examine the expression it builds.

And my object is

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

}

I call the method like this

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

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

The reason i pass the age as string is, i will be getting this value from XML.

It is creating Action for FirstName without any error whereas for Age it blows.

Error happens in this line for Age :

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

Error:

ParameterExpression of type 'System.Int32' cannot be used for delegate parameter of type 'System.String'

Can I do something with dynamic..?

I'm hoping someone will have some solution. Thanks

You should call Convert.ChangeType for type conversion:

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);
}

The problem is the following:

You are returning an Expression<Action<T,string>> , which basically means that the result will be a string . On the other hand, you are passing in "Age" as the name of the field the action should return. Age however is of type int , not string .

You can solve this in at least two ways:

  1. Add a second generic parameter to your GetAction method that specifies the return type.
  2. Add a call to ToString on the returned property to the expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM