表达式树和调用委托
所以我有一个 delegate
,它指向一些我在第一次创建 delegate
对象时实际上并不知道的函数。该对象稍后被设置为某些功能。
然后,我还想创建一个用参数调用委托的表达式树(为了这个问题,参数可以是 5
)。这就是我正在努力解决的问题;下面的代码显示了我想要的内容,但它无法编译。
Func<int, int> func = null;
Expression expr = Expression.Invoke(func, Expression.Constant(5));
对于这个例子,我可以这样做(这很实用,因为我需要在运行时构建表达式树):
Func<int, int> func = null;
Expression<Func<int>> expr = () => func(5);
这使得 expr
变成:
() => Invoke(value(Test.Program+<>c__DisplayClass0).func, 5)
这似乎意味着使用 delegate
func
,我需要生成 value(Test.Program+<>c__DisplayClass0).func
位。
那么,如何制作一个调用委托的表达式树呢?
So I have a delegate
which points to some function which I don't actually know about when I first create the delegate
object. The object is set to some function later.
I also then want to make an expression tree that invokes the delegate with an argument (for this question's sake the argument can be 5
). This is the bit I'm struggling with; the code below shows what I want but it doesn't compile.
Func<int, int> func = null;
Expression expr = Expression.Invoke(func, Expression.Constant(5));
For this example I could do (this is practical since I need to build the expression trees at runtime):
Func<int, int> func = null;
Expression<Func<int>> expr = () => func(5);
This makes expr
become:
() => Invoke(value(Test.Program+<>c__DisplayClass0).func, 5)
Which seems to mean that to use the delegate
func
, I need to produce the value(Test.Program+<>c__DisplayClass0).func
bit.
So, how can I make an expression tree which invokes a delegate?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为您想要做的是使用委托的 Target 和 Method 属性来传递创建 Call 表达式。基于 JulianR 的示例,它看起来像这样:
I think what you want to do is use the Target and Method properties of the delegate to pass to create a Call expression. Building on JulianR's sample, this is what it would look like:
好的,这展示了它是如何完成的(但在我看来这是非常不优雅的):
本质上我使用
(x) =>; func(x);
创建一个调用委托指向的函数。但你可以看到expr
过于复杂。因此,我认为这个答案不好,但也许可以建立在这个基础上?OK, this shows how it can be done (but it is very inelegant in my opinion):
Essentially I use
(x) => func(x);
to make a function that calls what the delegate points to. But you can see thatexpr
is overly complicated. For this reason I don't consider this answer good, but maybe it can be built upon?虽然其他答案提供了一些工作方法,但有一个较短的方法:
Expression.Invoke(Expression.Constant(my_delegate),parameter_for_delegate)
它适用于引用静态方法和实例方法的委托,无需任何更改。
While other answers provide some working ways there's a shorter one:
Expression.Invoke(Expression.Constant(my_delegate), parameter_for_delegate)
It works both for delegates referencing static methods and instance methods with no change.
这应该可行:
表达式可能很麻烦,但请记住:表达式总是由其他表达式构建而成。表达式是描述代码的其他表达式的树。您不能像在示例中那样传递实际委托,您需要的是该委托的表达式,通过说表达式需要委托类型的参数。然后您说您想要使用参数“5”调用该参数的方法,即
Invoke
方法。之后的所有其他内容只是如果您想将表达式转换为可运行的代码,您可能会这样做。不过,我用 .NET4 运行了这个,我希望我没有混合仅 .NET4 的表达式内容。
编辑回应PythonPower的评论:
我认为你想要的(不将委托作为参数传递)只能在委托本身被描述为表达式时才能完成,如下所示:
唯一的其他方法我能想到的是捕获在闭包中本地声明的委托,但我不知道该怎么做。
This should work:
Expressions can be a mindfuck, but remember: expressions are always built up out of other expressions. An expression is a tree of other expressions that describes code. You can't pass in the actual delegate like you do in your example, what you need is an expression of that delegate, by saying the expression expects a parameter of the type of your delegate. Then you say you want to call a method on that parameter, namely the
Invoke
method, with the argument '5'. All the other stuff after that is just if you want to turn the expression into runnable code, which you probably do.I ran this with .NET4 though, I hope I haven't mixed in .NET4 only expression stuff.
EDIT In response to PythonPower's comment:
I think what you want (not passing in the delegate as an argument) can only be done when the delegate itself is described as an expression, like this:
The only other way I can think of is to capture an delegate declared locally in a closure, but I wouldn't know how to do that.