For delegate parameters of type 'System.String,' a parameterExpression of type 'System.Int32' cannot be used.

c# delegates dynamic expression-trees generics

Question

Here is my code for generating an universal setter using an expression tree.

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 do not dial..Compile() I used the aforementioned technique because I wanted to check the expression it creates.

And my goal is

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

}

I use this method's name:

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

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

I send the age as a string since I'll be obtaining this number via XML, which is why I do.

Action is being created forFirstName without any mistakes, except forAge It sways.

This line contains an error forAge :

 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 use dynamic to achieve something?

I'm hoping someone has a solution. Thanks

1
4
5/29/2013 7:42:49 AM

Accepted Answer

Convert.ChangeType is the number to dial 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);
}
4
3/29/2012 5:48:12 PM

Popular Answer

The issue is as follows:

You are giving back anExpression<Action<T,string>> , which essentially indicates that the outcome will be astring . The name of the field that the action should return, on the other hand, is "Age," which you are passing in.Age but is of typeint , notstring .

This may be resolved in one of two ways:

  1. A second generic argument should be added.GetAction a technique that specifies the return type.
  2. Insert a call toToString on the expression's returned attribute.


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow