我有一个表达式树表达式
var lambdaExpr
编译时会生成
Action<Type,int>
但是我想包装它并生成一个表达式,在编译时会生成
Action<object, int>
我需要强制对动作的第一个参数强制转换,然后在将它传递给原始lambda之前将其转换为
object --- cast ---> Type
如果无法进行强制转换,那么在执行时显然会通过运行时异常。
如何将原始表达式树表达式包装到新表达式中?
具体来说,我需要在下面指出的地方添加一些额外的代码,以使类型正确。
private static Action<object, TProp> GenerateSetter<TProp>(Type type, string propertyName )
{
var property = type.GetProperty
(propertyName, BindingFlags.Public
| BindingFlags.Instance
| BindingFlags.NonPublic);
MethodInfo setterMethodInfo = property.SetMethod;
ParameterExpression paramo = Expression.Parameter(type, "param");
ParameterExpression parami = Expression.Parameter(typeof(TProp), "newvalue");
MethodCallExpression methodCallSetterOfProperty =
Expression.Call(paramo, setterMethodInfo, parami);
Expression setPropertyValueExp =
Expression.Lambda(methodCallSetterOfProperty, paramo, parami);
// This line below fails because setPropertyValueExp is an
// Action with first argument
// being the type passed in at runtime. I need to wrap it with a lambda that
// casts the object to the correct type.
var setPropertyValueLambda =
( Expression<Action<object, TProp>> ) setPropertyValueExp;
var setterFunc = setPropertyValueLambda.Compile();
return setterFunc;
}
答案 0 :(得分:3)
你需要拿走你的Action<Type,int>
lambda并生成一个Action<object,int>
lambda来执行演员并调用它:
var p=Expression.Parameter(typeof(object));
var conversion=Expression.Convert(p,type);
var call=Expression.Invoke(setPropertyValueExp,conversion);
var lambda=Expression.Lambda(call,p);
return lambda.Compile() as Action<object,int>;
答案 1 :(得分:1)
您应该将演员表添加到表达式中(使用Expression.Convert
):
private static Action<object, TProp> GenerateSetter<TProp>(Type type, string propertyName )
{
var property = type.GetProperty
(propertyName, BindingFlags.Public
| BindingFlags.Instance
| BindingFlags.NonPublic);
MethodInfo setterMethodInfo = property.SetMethod;
ParameterExpression paramo = Expression.Parameter(typeof(object), "param");
ParameterExpression parami = Expression.Parameter(typeof(TProp), "newvalue");
MethodCallExpression methodCallSetterOfProperty =
Expression.Call(Expression.Convert(paramo, type), setterMethodInfo, parami);
var setPropertyValueExp =
Expression.Lambda<Action<object, TProp>>(methodCallSetterOfProperty, paramo, parami);
var setterFunc = setPropertyValueExp.Compile();
return setterFunc;
}