c# – DLR LambdaExpressions和System.Runtime.CompilerServices.Closure对象
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – DLR LambdaExpressions和System.Runtime.CompilerServices.Closure对象,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2965字,纯文字阅读大概需要5分钟。
内容图文
![c# – DLR LambdaExpressions和System.Runtime.CompilerServices.Closure对象](/upload/InfoBanner/zyjiaocheng/783/b4201f3e2fd64e35aec7ece8c89152a1.jpg)
我正在为Microsoft DLR开发一种小型编程语言,并且在调用我的匿名方法时遇到了一些问题.具体来说,代码:
Delegate CompiledBody = Expression.Lambda(rt.Parser.ParseSingle(Body), parms).Compile();
因此,parms是一个包含单个ParameterExpression的数组,第一个参数包含用于定义匿名函数的相应表达式.当我尝试在CompiledBody.Method(MethodInfo)上使用Expression.Call调用我的Delegate时,收到错误:
Unhandled Exception: System.ArgumentException: Expression of type 'System.Object'
cannot be used for parameter of type 'System.Runtime.CompilerServices.Closure'
of method 'Shiro.Runtime.ShiroAtom lambda_method(System.Runtime.CompilerServices
.Closure, Shiro.Runtime.ShiroAtom)'
现在,在我的单参数方法的某个地方获得了第二个参数,类型为System.Runtime.CompilerServices.Closure(第二个,类型为ShiroAtom,是我的参数).这是有道理的,除了(a)我真的不在乎这个上下文中的方法是否在Closure范围内而且(b)我似乎无法创建一个空的Closure范围来传递这个参数.
我很感激任何帮助!提前致谢.
编辑:基于以下令人敬畏的答复的一些额外信息:
这段代码出现在我的Parser的深处.我有一个令牌流(实际上是Atoms),它被翻译成AST.这个特定的位是函数调用解析例程.它创建了一个CompiledBody,然后尝试使用以下内容调用它:
return Expression.Call(CompiledBody.Method, Expression.Constant("argument"));
生成的Lambda代表一个函数.基于我的架构,我只能调用DynamicInvoke或只调用Compiled Delegate,这不是其中之一.我希望我能提供一个更实际的例子,但这种情况发生在一个手工编码的解析器中,它会占用太多的代码来真正沟通为什么情况是这样的,但我真的需要一种方法来调用通过Expression.Call编译Lambda,如上所示.
问题的症结在于我的Compiled Lambda需要一个额外的参数来指定我指定的参数,一个CompilerServices.Closure,我不知道如何制作一个.
解决方法:
如果您可以共享正在编译的正文,那将会很有帮助,因为它将包含实际的闭包以及您如何调用它.我的猜测是你试图以某种方式“手动”调用结果委托,而不是保留委托对象的某些东西,只是生成一个Invoke表达式.如果你想使用DLR闭包,它应该是这样的:
using System;
using System.Linq.Expressions;
class Program {
static void Main(string[] args) {
var outerParam = Expression.Parameter(typeof(int), "outerParam");
var lambda =
Expression.Lambda<Func<int, Action>>(
Expression.Lambda<Action>(
Expression.Call(
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }),
Expression.Convert(outerParam, typeof(object))
)
),
outerParam
).Compile();
var actionParam = Expression.Parameter(typeof(Action), "action");
var lambdaInvoker =
Expression.Lambda<Action<Action>>(
Expression.Invoke(actionParam),
actionParam
).Compile();
lambdaInvoker(lambda(100));
lambdaInvoker(lambda(200));
Console.ReadLine();
}
}
这会产生3个lambda:第1个包含第2个内部lambda,它关闭一个参数.生成的闭包委托的类型是创建lambda表达式时指定的类型,即使那里有一个额外的隐藏参数.第3个lambda显示了如何从另一个lambda调用它 – 即通过委托调用.最后,我们将代表们联系起来,展示它是如何运作的.
还有一点需要注意的是,由于CLR的限制,DLR闭包现在实际上并没有那么好.创建闭包实际上是一个非常缓慢的过程,因为它需要通过反射而不是直接创建委托.如果您担心委托的性能,您将希望通过您自己的数据结构跟踪变量并关闭值(这是IronRuby和IronPython所做的事情).
内容总结
以上是互联网集市为您收集整理的c# – DLR LambdaExpressions和System.Runtime.CompilerServices.Closure对象全部内容,希望文章能够帮你解决c# – DLR LambdaExpressions和System.Runtime.CompilerServices.Closure对象所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。