动态创建基类的类型和调用构造函数

我需要动态创建一个类。 大多数工作正常,但我坚持生成构造函数。

AssemblyBuilder _assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyBuilder"), AssemblyBuilderAccess.Run); ModuleBuilder _moduleBuilder = _assemblyBuilder.DefineDynamicModule("MyModule"); public static object GetInstance(this TSource source, string eventName) where TSource : class { var typeName = "MyTypeName"; var typeBuilder = _moduleBuilder.DefineType(typeName, TypeAttributes.Class | TypeAttributes.Public); // create type like class MyClass : GenericType var baseNotGenericType = typeof(GenericType); var baseType = baseNotGenericType.MakeGenericType(typeBuilder, typeof(TSource), typeof(TEventArgs)); typeBuilder.SetParent(baseType); // the base class contains one constructor with string as param var baseCtor = baseNotGenericType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, new Type[0]); var ilGenerator = ctor.GetILGenerator(); // i want to call the constructor of the baseclass with eventName as param ilGenerator.Emit(OpCodes.Ldarg_0); // push "this" ilGenerator.Emit(OpCodes.Ldstr, eventName); // push the param ilGenerator.Emit(OpCodes.Call, baseCtor); ilGenerator.Emit(OpCodes.Ret); var type = typeBuilder.CreateType(); // return ... } 

在调用构造函数时,我得到一个BadImageFormatException。 我究竟做错了什么?

按照要求:

BaseClass看起来像这样:

 public abstract class GenericType : BaseClass where GT: GenericType, new() where TEventArgs : EventArgs where TEventSource : class { protected GenericType(string eventName) { _eventName = eventName; } // ... } 

我想在运行时得到什么:

 public class MyType : BaseClass { protected MyType() : base("SomeName") { } } 

我认为问题是你试图调用开放generics类型GenericType的构造函数,但是你需要调用闭合类型BaseClass的构造函数。 解决方案似乎很简单:

 var baseCtor = baseType.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); 

问题是这不起作用并抛出NotSupportedException 。 因此,似乎获得了generics类型的构造函数,其中一个参数是TypeBuilder是坚定的支持。

因此,我认为使用Reflection.Emit是不可能的,除非有一些黑客可以解决这个问题。

编辑: A-HA! 我不得不深入研究Reflector中的Reflection.Emit (尽管在文档中查找正确的位置也会有效) ,但我发现它:有一个特殊的方法: 静态TypeBuilder.GetConstructor() 。 所以这应该工作:

 var baseNonGenericCtor = baseNotGenericType.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); var baseCtor = TypeBuilder.GetConstructor(baseType, baseNonGenericCtor); 

最简单的方法是将抽象和派生类编译成一个简单的程序集,然后使用“Reflection.Emit”语言在Reflector中打开它们作为插件提供:

http://reflectoraddins.codeplex.com/

反射器:Reflection.Emit语言

是的,这听起来很酷:)