尽管此问题与此问题相似,但如何在运行时将方法附加到动态创建的C#类型上?,它不包含我要查找的答案。
我正在动态创建一个类型,然后将其保存在一个动态程序集DLL中,该DLL可在另一个项目中使用。
但是,我想将C#静态方法附加到此动态类型并在构造函数中调用它。 (因为此方法有点复杂)。
可以做到的一种方法是在另一个项目中用C#编写该方法,然后在动态类型中使用反射来调用它。但是,这将意味着动态类型必须随第二个程序集一起提供。
另一种方法是动态创建方法,然后为此编写IL。我想避免这种情况,因为我认为这会花费太多精力。有没有办法采用C#编写的现有方法,然后将其复制为动态类型?
更新
我当前正在使用AssemblyBuilder和ModuleBuilder.DefineType创建新类型。
我已经尝试使用MethodInfo.GetMethodBody()。GetILAsByteArray()来获取方法主体,然后使用MethodBuilder.CreateMethodBody()设置新定义的方法主体,但是由于某种原因无法正常工作。我注意到IL代码只有〜450个字节,这对我来说似乎太小了,因为其中有几个字符串文字很容易用完这个空间。我想我还需要做一些额外的事情才能使这项工作完成。
作为附带的问题,是否可以将整个类型复制到动态程序集中?
解决方案有点晚了,但我使用表达式树解决了这个问题,并将其编译为在此处回答,以回应此SO问题。总结:
使用表达式树,而不必发出原始IL。
var queue = new Queue< Expression>(); var arguments = Expression.Parameter(typeof(string []), args); queue.Enqueue(Expression.Call(typeof(Console).GetMethod( WriteLine,new Type [] {})))); var块= Expression.Block(queue); var lambda = Expression.Lambda< Func< string [],int>>(block,new ParameterExpression [] {arguments}); lambda.CompileToMethod(builderMethod); // builderMethod是先前创建的MethodBuilder实例。这确实非常强大,并且绝对适合使用ILGenerator不需要微穿孔的情况。 / p>
Although this question is similar to this question, How do I attach a method to a dynamically-created C# type at runtime?, it does not contain the answer I am looknig for.
I am creating a type dynamically, and then saving this in a dynamic assembly DLL, which can be used in another project.
However, I want to "attach" a C# static method to this dynamic type and call it in the constructor. (since this method is a little complicated).
One way this can be done is to write the method in C# in another project, then use reflection in the dynamic type to invoke it. However, this would mean that the dynamic type will have to ship with a second assembly.
Another way would be to create the method dynamically and then write the IL for this. I would like to avoid this, since I think it would take too much effort. Is there a way to take an existing method written in C# and just "copy" it to the dynamic type?
Update
I am currently creating the new type using AssemblyBuilder, and ModuleBuilder.DefineType.
I have already tried grabbing the method body using MethodInfo.GetMethodBody().GetILAsByteArray() and then setting the newly defined method body using MethodBuilder.CreateMethodBody(), but does not work for some reason. I noticed that the IL code is only ~450 bytes, which seems too small for me, because there are several string literals in there that would easily use up this space. I am guessing there is some additional things I need to do to make this work.
As a side question, is it possible to copy an entire type into my dynamic assembly?
解决方案A little late but I solved this using Expression Trees and compiling them into the MethodBuilder as answered here in response to this SO question. In summary:
Using Expression Trees instead of having to emit raw 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.This is very powerful indeed and definitely suited for situations where micro-perf is not required using ILGenerator.
更多推荐
在不使用IL的情况下,将现有的C#方法附加到动态创建的Type中
发布评论