动态创建基类的类型和调用构造函数
我需要动态创建一个类。 大多数工作正常,但我坚持生成构造函数。
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/
是的,这听起来很酷:)