Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Net标准中CompileToMethod的替代方案_C#_.net_.net Core_.net Standard - Fatal编程技术网

C# Net标准中CompileToMethod的替代方案

C# Net标准中CompileToMethod的替代方案,c#,.net,.net-core,.net-standard,C#,.net,.net Core,.net Standard,我现在正在将一些使用表达式的库移植到.Net Core应用程序中,遇到了一个问题,即我的所有逻辑都基于LambdaExpression.CompileToMethod,这在中根本不存在。以下是示例代码: public static MethodInfo CompileToInstanceMethod(this LambdaExpression expression, TypeBuilder tb, string methodName, MethodAttributes attributes) {

我现在正在将一些使用表达式的库移植到
.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);

    ...
}
publicstaticmethodinfo CompileToInstanceMethod(这个LambdaExpression表达式、TypeBuilder tb、stringmethodname、MethodAttributes)
{
...
var method=tb.DefineMethod($“u StaticProxy”,MethodAttributes.Private | MethodAttributes.Static,proxy.ReturnType,paramTypes);
表达式。编译方法(method);
...
}
是否有可能以某种方式重写它,以便能够使用表达式生成方法?我已经可以用
Emit
来实现它,但是它非常复杂,我希望避免使用高级表达式

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

System.InvalidOperationException:无法导入全局方法或 来自不同模块的字段


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

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

  • 如果您查看
    CompileToMethod
    实现,您将看到它使用内部
    LambdaCompiler
  • 如果你深入研究,你会发现
    LambdaCompiler
    使用
    System.Reflection.Emit
    将lambda转换成
    MethodInfo
  • System.Reflection.Emit
    受.NET内核支持
  • 考虑到这一点,我的建议是尝试重用
    LambdaCompiler
    源代码。你可以找到它
  • 此解决方案的最大问题是:

  • LambdaCompiler
    分布在许多文件中,因此查找编译它所需的内容可能很麻烦
  • LambdaCompiler
    可能使用一些.NET核心根本不支持的API
  • 还有几点意见:

  • 如果要检查哪个平台支持哪个API,请使用
  • 如果您想查看.NET标准版本之间的差异,请使用网站

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

    感觉有点像黑客,但它可以工作,并且可能比尝试通过LambdaCompiler重新创建CompileToMethod功能更容易

    试图使LambdaCompiler在.NET Core上工作 基于Michal Komorowski的回答,我决定尝试将
    LambdaCompiler
    移植到.NET核心。你可以找到我的努力(GitHub链接)。事实上,该类分布在多个文件上是这里最小的问题之一。一个更大的问题是它依赖于.NET核心代码库中的内部部分

    引用我在GitHub回购协议中的话:

    不幸的是,这并非微不足道,因为(至少)以下问题:

    • AppDomain.CurrentDomain.DefinedDynamicAssembly在.NET Core中不可用-AssemblyBuilder.DefinedDynamicAssembly替换为。这个答案描述了如何使用它

    • Assembly.DefinitionInformationSource不可用

    • 依赖内部方法和属性,例如BlockExpression.ExpressionCount、BlockExpression.GetExpression、BinaryExpression.IsLiftedLogical等

    出于上述原因,试图将此工作作为一个独立的包来完成,实际上是徒劳的。唯一可行的方法是将其包含在.NETCore中

    然而,由于其他原因,这是有问题的。我认为许可证是这里的绊脚石之一。其中一些代码可能是作为DLR工作的一部分编写的,而DLR本身也获得了Apache许可。一旦代码库中有第三方贡献者的贡献,重新授权它(到麻省理工学院,就像.NET核心代码库的其余部分一样)或多或少是不可能的

    其他选择 我认为目前最好的选择是以下两种情况之一,具体取决于用例:

    • 使用,可从NuGet(Apache 2.0-licensed)获得。这是授权的运行时,据我所知,这是唯一一种主动维护的DLR支持的语言。(IronRuby和IronJS似乎都被有效地抛弃了。)DLR允许您使用
      Microsoft.Scripting.Ast.lambdaulder
      定义lambda表达式;不过,IronPython似乎没有直接使用它。还有
      Microsoft.Scripting.解释器.LightCompiler
      类,它似乎非常有趣

      不幸的是,DLR的文档记录似乎很差。我想有一个wiki被引用了,但是它是离线的(可以通过下载CodePlex上的存档文件来访问)

    • 使用Roslyn为您编译(动态)代码。这可能也有一点学习曲线;不幸的是,我自己对它还不是很熟悉

      这似乎有相当多的策划链接,教程等:。我建议以此为出发点。如果您对动态构建方法特别感兴趣,那么这些方法似乎也值得一读: