3

在构建表达式树时,我必须使用调用外部方法的节点来获取表达式然后可以继续评估的值。这些方法是提供的Func<T>,我的代码不知道它们的来源。

执行上述调用的最正确方法是什么?我试过这样的事情:

private Dictionary<string, Delegate> _externalSymbols;

private Expression _forExternalSymbol(string identifier)
{
    Delegate method = _externalSymbols[identifier];
    return Expression.Call(method.Method);
}

只要method从字典中获取的内容是在编译时创建的,它就可以工作。但是,如果Func<T>是动态方法,例如,通过在运行时编译另一个表达式,这将无法解决抛出

ArgumentException:为调用方法“Int32 lambda_method(System.Runtime.CompilerServices.ExecutionScope)”提供的参数数量不正确

可以通过将给定函数包装到一个额外的表达式中来实现所需的效果,但与它过去的样子相比,这似乎非常可怕:

private Expression _forExternalSymbol(string identifier)
{
    Delegate method = _externalSymbols[identifier];
    Expression mediator = method is Func<double> ?
        (Expression)(Expression<Func<double>>)(() => ((Func<double>)method)()) :
        (Expression<Func<string>>)(() => ((Func<string>)method)());
    return Expression.Invoke(mediator);
}

此外,如果我需要添加对double和以外的类型的支持,这几乎不是一种可扩展的方法string

我想知道是否有更好的选项可以与动态创建的方法一起使用(最好适用于 .NET 3.5)。

4

1 回答 1

2

只要method从字典中获取的内容是在编译时创建的,它就可以工作

不,只要method是静态的,它就可以工作。例如,如果委托是一个从其父分数引用某些东西的 lambda(即它是一个闭包),它也将不起作用。

调用委托的正确方法是使用Expression.Invoke(). 要获得Expression代表您的代表的代表,请使用Expression.Constant()

Expression.Invoke(Expression.Constant(method)))
于 2014-01-04T20:52:47.833 回答