2012-03-29 83 views
3

我使用表达式树创建一个一般的setter和这里的委托参数是我的代码ParameterExpression不能被用于类型“System.String”

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

我不在上面的方法中调用.Compile(),因为我想检查它构建的表达式。

而我的目标是

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

} 

我调用该方法是这样

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

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

我之所以传递年龄字符串,我会越来越从XML此值。

它正在创建FirstName的行动没有任何错误,而对于Age它吹。

错误发生在这一行Age

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

错误:

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

我可以做动态的东西..?

我希望有人会有一些解决方案。由于

+1

你为什么不只是将它传递给操作之前投的年龄为int? – 2012-03-29 14:40:51

回答

3

你应该叫Convert.ChangeType进行类型转换:

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

太棒了。有用。谢谢Balazs Tihanyi。 – kans 2012-03-30 07:06:46

+1

我很高兴它帮助你。请不要忘记将其标记为已接受的答案。 – 2012-03-30 20:52:47

2

的问题如下:

您正在返回一个Expression<Action<T,string>>,这基本上意味着,其结果将是一个string。另一方面,您传递的是“年龄”作为该行为应该返回的字段的名称。 Age然而是int类型,而不是string

可以在至少两种方式解决这个问题:

  1. 添加第二个泛型参数到您的GetAction方法指定的返回类型。
  2. 将返回属性上的ToString添加到表达式中。
相关问题