我正在使用表达式树创建一个通用的setter,这是我的代码
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");
我将age作为字符串传递的原因是,我将从XML中获取此值。
正在为FirstName
创建操作而不会出现任何错误,而对于Age
则会出现错误。
Age
的这一行发生错误:
return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);
错误:
类型'System.Int32'的ParameterExpression不能用于'System.String'类型的委托参数
我能用动态做什么吗??
我希望有人会有一些解决方案。谢谢
答案 0 :(得分: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 :(得分:2)
问题如下:
您将返回Expression<Action<T,string>>
,这基本上意味着结果将是string
。另一方面,您传入“Age”作为操作应返回的字段的名称。 Age
但是int
类型,而不是string
。
您可以通过以下两种方式解决此问题:
GetAction
方法添加第二个通用参数。ToString
添加对表达式的调用。