在动态创建的Type中附加现有的c#方法,而不使用IL

本文关键字:方法 IL Type 创建 动态 | 更新日期: 2023-09-27 18:16:48

虽然这个问题与这个问题类似,我如何在运行时将一个方法附加到动态创建的c#类型上?,它不包含我正在寻找的答案。

我动态创建一个类型,然后将其保存在一个动态程序集DLL中,可以在另一个项目中使用。

然而,我想给这个动态类型"附加"一个c#静态方法,并在构造函数中调用它。(因为这个方法有点复杂)。 一种方法是在另一个项目中用c#编写方法,然后在动态类型中使用反射来调用它。但是,这将意味着动态类型必须附带第二个程序集。

另一种方法是动态创建方法,然后为其编写IL。我想避免这样做,因为我认为这会花费太多精力。是否有一种方法可以使用c#编写的现有方法并将其"复制"到动态类型?

我目前正在使用AssemblyBuilder和ModuleBuilder.DefineType创建新类型。

我已经尝试使用methodinfoo . getmethodbody (). getilasbytearray()抓取方法体,然后使用MethodBuilder.CreateMethodBody()设置新定义的方法体,但由于某种原因不起作用。我注意到IL代码只有~450字节,这对我来说似乎太小了,因为其中有几个字符串字面值很容易耗尽这个空间。我想我还需要做一些额外的事情来完成这项工作。

作为附带问题,是否可以将整个类型复制到我的动态程序集中?

在动态创建的Type中附加现有的c#方法,而不使用IL

有点晚了,但我使用表达式树解决了这个问题,并将它们编译到MethodBuilder中,这里回答了这个问题。总之:

使用表达式树而不是必须发出原始IL。

var queue = new Queue<Expression>();
var arguments = Expression.Parameter(typeof(string []), "args");
queue.Enqueue(Expression.Call(typeof(Console).GetMethod("WriteLine", new Type [] { })));
var block = Expression.Block(queue);
var lambda = Expression.Lambda<Func<string [], int>>(block, new ParameterExpression [] { arguments });
lambda.CompileToMethod(builderMethod);
// builderMethod is a MethodBuilder instance created earlier.

这确实非常强大,绝对适合使用ILGenerator不需要微穿孔的情况。