【问题标题】:How to cast an expression tree lambda in c#?如何在 C# 中转换表达式树 lambda?
【发布时间】:2014-02-04 01:40:25
【问题描述】:

我有一个表达式树表达式

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

【问题讨论】:

    标签: c# casting lambda expression-trees


    【解决方案1】:

    您需要使用您的 Action&lt;Type,int&gt; lambda 并生成一个 Action&lt;object,int&gt; 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>;
    

    【讨论】:

      【解决方案2】:

      您应该将演员表添加到您的表达式中(使用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;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-01-15
        • 1970-01-01
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多