Ale*_*kiy 16 .net c# .net-core .net-standard
我现在正在移植一些使用表达式到.Net Core应用程序的库,并遇到了一个问题,我的所有逻辑都基于这个问题LambdaExpression.CompileToMethod.这里是示例代码:
public static MethodInfo CompileToInstanceMethod(this LambdaExpression expression, TypeBuilder tb, string methodName, MethodAttributes attributes)
{
...
var method = tb.DefineMethod($"<{proxy.Name}>__StaticProxy", MethodAttributes.Private | MethodAttributes.Static, proxy.ReturnType, paramTypes);
expression.CompileToMethod(method);
...
}
Run Code Online (Sandbox Code Playgroud)
是否有可能以某种方式重写它以使用表达式生成方法成为可能?我已经可以使用Emit但它非常复杂,我想避免它支持高级表达式.
我尝试使用var method = expression.Compile().GetMethodInfo();但在这种情况下我收到一个错误:
System.InvalidOperationException:无法从其他模块导入全局方法或字段.
我知道我可以手动发出IL,但我需要完全转换Expression- > MethodInfo绑定到特定TypeBuilder而不是DynamicMethod在它上面构建自己.
它不是一个理想的解决方案,但如果您不想从头开始编写所有内容,则值得考虑:
CompileToMethod实现,你会发现它使用了内部LambdaCompiler类.LambdaCompiler使用System.Reflection.Emit到lambda表达式转换成MethodInfo.System.Reflection.Emit .NET Core支持.LambdaCompiler源代码.你可以在这里找到它.该解决方案的最大问题是:
LambdaCompiler 在许多文件中传播,因此找到编译它所需的内容可能很麻烦.LambdaCompiler 可能会使用.NET Core不支持的某些API.一些额外的评论:
根据 Michal Komorowski 的回答,我决定尝试移植LambdaCompiler到 .NET Core。您可以在这里找到我的成果(GitHub 链接)。事实上,该类分布在多个文件中,这确实是这里最小的问题之一。一个更大的问题是它依赖于 .NET Core 代码库中的内部部分。
引用我自己在上面的 GitHub 存储库中的内容:
不幸的是,由于(至少)以下问题,这并非易事:
AppDomain.CurrentDomain.DefineDynamicAssembly 在 .NET Core 中不可用 - AssemblyBuilder.DefineDynamicAssembly 取代了它。这个 SO 答案描述了如何使用它。
Assembly.DefineVersionInfoResource 不可用。
依赖内部方法和属性,例如 BlockExpression.ExpressionCount、BlockExpression.GetExpression、BinaryExpression.IsLiftedLogical 等。
由于上述原因,尝试将其作为一个独立的包来工作本质上是没有成果的。实现此功能的唯一现实方法是将其包含在 .NET Core 中。
然而,由于其他原因,这是有问题的。我相信许可是这里的绊脚石之一。其中一些代码可能是作为 DLR 工作的一部分编写的,它本身已获得 Apache 许可。一旦您在代码库中获得了第 3 方贡献者的贡献,重新授权它(像 .NET Core 代码库的其余部分一样,授予 MIT)就或多或少是不可能的。
我认为,根据用例,目前您最好的选择是以下两个之一:
使用DLR(动态语言运行时),可从 NuGet(Apache 2.0 许可)获得。这是为IronPython提供支持的运行时,据我所知,IronPython 是唯一积极维护的 DLR 支持的语言。(IronRuby 和 IronJS 似乎都已被有效放弃。)DLR 允许您使用Microsoft.Scripting.Ast.LambdaBuilder;定义 lambda 表达式。但这似乎并没有被 IronPython 直接使用。还有一Microsoft.Scripting.Interpreter.LightCompiler堂课,看起来也挺有趣的。
不幸的是,德国航天中心的记录似乎相当缺乏。我认为CodePlex 站点引用了一个 wiki ,但它处于离线状态(不过可以通过在 CodePlex 上下载存档来访问)。
使用 Roslyn 为您编译(动态)代码。这可能也有一些学习曲线;不幸的是,我自己对它还不是很熟悉。
这似乎有很多精选的链接、教程等:https://github.com/ironcev/awesome-roslyn。我建议将此作为起点。如果您对动态构建方法特别感兴趣,这些似乎也值得一读:
以下是罗斯林其他一些常规阅读链接。然而,这些链接中的大多数都集中在分析此处的 C# 代码(这是 Roslyn 的用例之一),但 Roslyn 也可用于生成IL 代码(即“编译”)C# 代码。
还有第三种选择,这对我们大多数人来说可能不感兴趣:
| 归档时间: |
|
| 查看次数: |
1597 次 |
| 最近记录: |