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

在动态创建的类型中附加现有的C#方法,而不使用IL,c#,dynamic,C#,Dynamic,虽然这个问题和这个问题很相似,但它并不包含我想要的答案 我正在动态创建一个类型,然后将其保存在动态程序集DLL中,该DLL可用于其他项目 但是,我想“附加”一个C#静态方法到这个动态类型,并在构造函数中调用它。(因为这个方法有点复杂) 一种方法是在另一个项目中用C#编写方法,然后在动态类型中使用反射来调用它。但是,这意味着动态类型必须附带第二个程序集 另一种方法是动态创建方法,然后为此编写IL。我想避免这种情况,因为我认为这需要太多的努力。有没有一种方法可以将用C#编写的现有方法“复制”到动态类

虽然这个问题和这个问题很相似,但它并不包含我想要的答案

我正在动态创建一个类型,然后将其保存在动态程序集DLL中,该DLL可用于其他项目

但是,我想“附加”一个C#静态方法到这个动态类型,并在构造函数中调用它。(因为这个方法有点复杂)

一种方法是在另一个项目中用C#编写方法,然后在动态类型中使用反射来调用它。但是,这意味着动态类型必须附带第二个程序集

另一种方法是动态创建方法,然后为此编写IL。我想避免这种情况,因为我认为这需要太多的努力。有没有一种方法可以将用C#编写的现有方法“复制”到动态类型

更新

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

我已经尝试使用MethodInfo.GetMethodBody().GetILAsByteArray()获取方法体,然后使用MethodBuilder.CreateMethodBody()设置新定义的方法体,但由于某些原因无法工作。我注意到IL代码只有约450字节,这对我来说似乎太小了,因为其中有几个字符串文本很容易占用这个空间。我猜我还需要做一些额外的事情来完成这项工作


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

有点晚了,但我使用表达式树解决了这个问题,并将它们编译到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.
var queue=new queue();
var参数=Expression.Parameter(typeof(string[]),“args”);
Enqueue(Expression.Call(typeof(Console.GetMethod)(“WriteLine”,新类型[]{}));
var block=Expression.block(队列);
var lambda=Expression.lambda(块,新参数Expression[]{arguments});
lambda.CompileToMethod(builderMethod);
//builderMethod是先前创建的MethodBuilder实例。

这确实非常强大,非常适合使用ILGenerator不需要micro perf的情况。

有点晚了,但我使用表达式树解决了这个问题,并将它们编译到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.
var queue=new queue();
var参数=Expression.Parameter(typeof(string[]),“args”);
Enqueue(Expression.Call(typeof(Console.GetMethod)(“WriteLine”,新类型[]{}));
var block=Expression.block(队列);
var lambda=Expression.lambda(块,新参数Expression[]{arguments});
lambda.CompileToMethod(builderMethod);
//builderMethod是先前创建的MethodBuilder实例。

这确实非常强大,非常适合使用ILGenerator时不需要micro perf的情况。

要附加的方法是否对新创建的类型有任何特定的作用?您使用什么来创建动态类型?反射。发射?唯一可行的方法是通过虚拟方法。也就是说,在构造函数中调用虚方法是完全不可能的。@AntonTykhyy:保存程序集的唯一方法是通过Reflection.Emit。@leppie:还有第三方库,如Mono.Cecil。使用Mono.Cecil,读取一个程序集、提取方法体(IL指令+异常块+局部签名)并将其复制到新程序集中的方法并不困难。使用Reflection.Emit,我想需要解析原始IL来替换元数据标记(并导入任何引用的类型、方法等)。您要附加的方法是否对新创建的类型有特定的作用?您使用什么来创建动态类型?反射。发射?唯一可行的方法是通过虚拟方法。也就是说,在构造函数中调用虚方法是完全不可能的。@AntonTykhyy:保存程序集的唯一方法是通过Reflection.Emit。@leppie:还有第三方库,如Mono.Cecil。使用Mono.Cecil,读取一个程序集、提取方法体(IL指令+异常块+局部签名)并将其复制到新程序集中的方法并不困难。使用Reflection.Emit,我认为需要解析原始IL来替换元数据标记(并导入任何引用的类型、方法等)