有没有办法设置' DeclaringType'在表达式树中?

时间:2015-12-14 22:09:30

标签: c# lambda expression-trees linq-expressions

我正在做 Func - &gt; 表达 - &gt; Func 转换。如果我从方法(下面的第一个示例)创建Func&lt;&gt;(),它可以正常工作但是如果我使用表达式树(第二个示例)创建函数,则在访问<时,它会失败并带有 NullReferenceException EM> func2.Method.DeclaringType.FullName 。这是因为 DeclaringType 为空。 (NJection使用反射,所以我认为这就是它需要DeclaringType的原因。)

如何为Func&lt;&gt;填写DeclaringType类型?那是通过编译表达式树创建的? (也许它不可能?)DeclaringType在第一个例子中设置。

使用Func&lt;&gt;从一个方法...(效果很好)

// Build a Func<> 
Func<int, int> add = Add;
// Convert it to an Expression using NJection Library
Expression<Func<int, int>> expr = ToExpr<Func<int, int>>(add);
// Convert it back to a Func<>
Func < int, int> func = expr.Compile();
// Run the Func<>
int result = func(100);

使用表达式树(不起作用)......

// Build a Func<> using an Expression Tree
ParameterExpression numParam = Expression.Parameter(typeof(int));
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numAddFive = Expression.Add(numParam, five);
Func<int, int> func2 = 
    Expression.Lambda<Func<int, int>>(
        numAddFive, 
        new ParameterExpression[] { numParam }).Compile();
// Convert to an Expression using NJection (EXCEPTION ON NEXT LINE)
// ToExpr is trying to access func2.Method.DeclaringType.FullName(DeclaringType is null)
Expression<Func<int, int>> exp2 = ToExpr<Func<int, int>>(func2);
// Convert it back to a Func<>
Func<int, int> func2b = exp2.Compile();
// Run the Func<>
int result2 = func2b(100);

2 个答案:

答案 0 :(得分:3)

我不知道NJection库的用途是什么,因为他们的网站已关闭且他们的Codeplex没有可用的源代码。

如果你只需要获得一个可以编译回函数的Expression,你可以自己创建它。例如。像这样:

static Expression<T> ToExpr<T>(T func)
{
    var type = typeof(T);
    var method = type.GetMethod("Invoke"); // Delegate.Invoke() has parameters types matching delegate parameters types
    var pars = method.GetParameters()
        .Select(pi => Expression.Parameter(pi.ParameterType))
        .ToArray();

    return Expression.Lambda<T>(
        Expression.Call(Expression.Constant(func), method, pars),
        pars
    );
}

使用此ToExpr,您的上述代码可以毫无问题地编译和运行。

答案 1 :(得分:2)

我猜不了。

当您将表达式编译为可执行文件Func时,它在技术上是一种动态方法。如果你打电话给func2.Method.GetType(),你可以看到这个。这将返回type DynamicMethodDeclaring Type始终为null