.Net Standard中CompileToMethod的替代品

我现在正在移植一些使用表达式到.Net Core应用程序的库,并遇到了一个问题,我的所有逻辑都基于LambdaExpression.CompileToMethod ,它只是遗漏了。这是示例代码:

 public static MethodInfo CompileToInstanceMethod(this LambdaExpression expression, TypeBuilder tb, string methodName, MethodAttributes attributes) { ... var method = tb.DefineMethod($"__StaticProxy", MethodAttributes.Private | MethodAttributes.Static, proxy.ReturnType, paramTypes); expression.CompileToMethod(method); ... } 

是否有可能以某种方式重写它以使用表达式生成方法成为可能? 我已经可以用Emit做到这一点,但它非常复杂,我想避免它支持高级表达式。

我尝试使用var method = expression.Compile().GetMethodInfo(); 但在这种情况下,我收到一个错误:

System.InvalidOperationException:无法从其他模块导入全局方法或字段。

我知道我可以手动发出IL,但我需要将Expression – >转换为绑定到特定TypeBuilder MethodInfo ,而不是在其上构建自己的DynamicMethod

将一些代码移植到netstandard时遇到了同样的问题。 我的解决方案是使用Compile方法将lambda编译为Func,将Func存储在我添加到动态类型的静态字段中,然后在我的动态方法中,我只需从该静态字段加载并调用Func。 这允许我使用LINQ Expression API而不是reflection发射来创建lambda(这本来很痛苦),但仍然让我的动态类型实现一个接口(这是我的场景的另一个要求)。

感觉有点像黑客,但它有效,并且可能比通过LambdaCompiler重新创建CompileToMethodfunction更容易。

它不是一个理想的解决方案,但如果您不想从头开始编写所有内容,则值得考虑:

  1. 如果您查看CompileToMethod实现,您将看到它使用内部LambdaCompiler类。
  2. 如果你深入挖掘,你会发现LambdaCompiler使用System.Reflection.Emit将lambdas转换为MethodInfo
  3. .NET Core支持System.Reflection.Emit
  4. 考虑到这一点,我的主张是尝试重用LambdaCompiler源代码。 你可以在这里找到它。

该解决方案的最大问题是:

  1. LambdaCompiler分布在许多文件中,因此找到编译它所需的内容可能很麻烦。
  2. LambdaCompiler可能会使用.NET Core不支持的某些API。

一些额外的评论:

  1. 如果要检查哪个平台支持哪个API,请使用.NET API目录 。
  2. 如果您想查看.NET标准版本之间的差异,请使用此站点。