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

时间:2011-12-02 15:11:19

标签: c# dynamic

虽然这个问题类似于How do I attach a method to a dynamically-created C# type at runtime?这个问题,但它不包含我想要的答案。

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

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

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

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

更新

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

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

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

1 个答案:

答案 0 :(得分:1)

有点晚了,但是我使用表达式树解决了这个问题,并将它们编译为方法构建器answered here以响应this SO question。总结:

使用表达式树而不必发出原始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不需要micro-perf的情况。