.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更容易。
它不是一个理想的解决方案,但如果您不想从头开始编写所有内容,则值得考虑:
- 如果您查看
CompileToMethod
实现,您将看到它使用内部LambdaCompiler
类。 - 如果你深入挖掘,你会发现
LambdaCompiler
使用System.Reflection.Emit
将lambdas转换为MethodInfo
。 - .NET Core支持
System.Reflection.Emit
。 - 考虑到这一点,我的主张是尝试重用
LambdaCompiler
源代码。 你可以在这里找到它。
该解决方案的最大问题是:
-
LambdaCompiler
分布在许多文件中,因此找到编译它所需的内容可能很麻烦。 -
LambdaCompiler
可能会使用.NET Core不支持的某些API。
一些额外的评论:
- 如果要检查哪个平台支持哪个API,请使用.NET API目录 。
- 如果您想查看.NET标准版本之间的差异,请使用此站点。
- 使用C#加载内存泄漏的图像
- Java ExecutorService.newSingleThreadExecutor()的C#等价物,或者:如何序列化对资源的multithreading访问
- 参考和值类型方案
- 有没有办法从ASP.NET WebMethod中获取原始SOAP请求?
- 如何在托管C ++中捕获非托管C ++exception
- 为什么新的Thread()接受方法名称,即使没有构造函数重载似乎允许这样做?
- 禁止WebBrowser控件中的“保存/打开”对话框
- 用于.NET 4.5 wpf项目的.NET 4.5 wpf项目的System.Windows.Interactivity
- Windows Mobile和VS2008无法连接到设备