首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将ILEmit DynamicMethod的内容内联到表达式树中

将ILEmit DynamicMethod的内容内联到表达式树中
EN

Stack Overflow用户
提问于 2013-11-02 04:09:01
回答 2查看 374关注 0票数 1

我有一个使用DynamicMethod生成ILEmit的方法,我想在表达式树中内联它的内容。我需要这样做,以便将表达式树写入程序集。

我可以编译DynamicMethod并将其包含到树中,但这会阻止我将表达式树写入程序集,但有以下错误:

CompileToMethod无法编译常量'BulkUtil+BlitMethodByte‘,因为它是一个重要的值,例如活动对象。相反,创建一个可以构造此值的表达式树。

因为我正在生成方法的主体,所以我想我应该将它内联到树中,这样就可以输出它。但是,由于该方法生成不安全的代码,所以我不知道如何直接翻译它。

有办法直接将IL添加到表达式树中吗?

EN

回答 2

Stack Overflow用户

发布于 2013-11-04 11:10:09

我认为试图将IL内联到表达式树中并不是正确的方法,因为这意味着您必须知道从表达式生成的IL看起来是什么样子(至少在某种程度上是这样)。而且,据我所知,没有简单的方法可以做到这一点。

相反,您可以做的是将IL方法创建为生成程序集中的普通MethodBuilder (即不是DynamicMethod),然后从表达式中调用该方法。

代码具有非常简单的IL和表达式,可以如下所示:

代码语言:javascript
复制
var assembly = AssemblyBuilder.DefineDynamicAssembly(
    new AssemblyName("a"), AssemblyBuilderAccess.RunAndSave);
var module = assembly.DefineDynamicModule("a.dll");

var ilType = module.DefineType("IlType");
var ilMethod = ilType.DefineMethod(
    "M", MethodAttributes.Public | MethodAttributes.Static,
    typeof(int), Type.EmptyTypes);
var il = ilMethod.GetILGenerator();
il.Emit(OpCodes.Ldc_I4, 42);
il.Emit(OpCodes.Ret);
var createdIlType = ilType.CreateType();

var expressionType = module.DefineType("ExpressionType");
var expressionMethod = expressionType.DefineMethod(
    "M", MethodAttributes.Public | MethodAttributes.Static,
    typeof(int), Type.EmptyTypes);
var lambda = Expression.Lambda<Func<int>>(
    Expression.Call(createdIlType.GetMethod("M")));
lambda.CompileToMethod(expressionMethod);
expressionType.CreateType();

assembly.Save("a.dll");

Expression似乎不能直接调用MethodBuilder,这意味着这两个方法必须位于不同的类型中,并且必须首先创建包含IL方法的类型。

票数 2
EN

Stack Overflow用户

发布于 2013-11-25 20:16:39

不幸的是,将表达式树写入方法是非常有限的。您只能编写静态方法,它们只能引用已经物化的类或方法。(即没有建筑商)。

在我完全放弃这个想法之前,我尝试了创建"stub“静态和实例方法的方法,该方法将调用具有同名被调用者的所有参数的委托。

例如:

代码语言:javascript
复制
public class MyClass<Proxy>
{
      static Func<MyClass,int,float,long,double,object> <Delegate>Foo
      public override object Foo(int a,float b,long c,double d){
          return MyClass_Proxy.<Delegate>Foo.Invoke(this,a,b,c,d)
      }
}

这样,由于一切都是物化的,表达式树可以引用所有成员。这是一次可怕的黑客攻击,后来发展成了一个动态代理。这起作用(我甚至可以说很好),直到您来到泛型方法或泛型类方法之后,它才会面目全非。

您可以看看我对这些代理的看法:https://bitbucket.org/mburbea/delegatedproxy/src、ProxiedTypeBuilder和ProxiedMethodBuilder完成了大部分基于类或接口创建代理类的艰苦工作。我的问题表面有点严重,因为我需要我的代理方法调用它们的基本实现的能力(这是大多数丑陋的代码所要做的),我想出了一个合适的方法来处理带有泛型参数的方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19738860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档