是否可以创建直接调用方法的表达式树?例如,请考虑以下方法:
public static int MyFunc(int a,int b) { return a + b; }
我想创建一个表达式树,调用MyFunc参数a = 1和b = 2.实现这一目标的一种方法是反思:
var c1 = Expression.Constant(1); var c2 = Expression.Constant(2); var expr = Expression.Call(typeof(Program).getmethod("MyFunc"),c1,c2);
但是,这是不利的,因为反射很慢并且应该将编译时错误转换为运行时错误.
我可以使用以下方法:
Expression<Func<int,int,int>> lambda = (a,b) => MyFunc(a,b); var expr = Expression.Invoke(lambda,c2);
但这仍然不是我想要的,因为它将方法包装在lambda表达式中而不是直接调用它.
Func<int,int> del = Program.MyFunc; var expr = Expression.Invoke(del,c2);
不幸的是,这不会编译,因为del是委托而不是表达式.有没有办法从委托构建表达式? (注意,我在编译时知道委托的目标,所以我不需要这里描述的那种灵活性:Expression Trees and Invoking a Delegate.)
更新:这也有效,但它仍然依赖于反射:
Func<int,int> del = Program.MyFunc; var expr = Expression.Call(del.Method,c2);
至少它更有可能在编译时捕获问题.但它仍然支付反射的运行时价格,不是吗?
解决方法
只要您在lambda上调用.Compile并存储(并重新使用)委托,您只需支付反映价格一次.
var c1 = Expression.Constant(1); var c2 = Expression.Constant(2); var expr = Expression.Call(typeof(Program).getmethod("MyFunc"),c2); Func<int> func = Expression.Lambda<Func<int>>(expr).Compile(); // ** Now store func and re-use it **
但是,要使裸代理只使用该方法,您可以使用:
var method = typeof(Program).getmethod("MyFunc"); Func<int,int> func = (Func<int,int>) Delegate.CreateDelegate( typeof(Func<int,int>),method);
当然,你被迫在调用者处提供常量.
另一个选项是Dynamicmethod,但只要您缓存最终委托,这将不会明显加快.它确实提供了更大的灵活性(以复杂的代价),但这似乎不是问题.
原文地址:https://www.jb51.cc/csharp/100279.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。