动态创建类型,并调用基类构造函数的(Dynamically create type and call

2019-06-23 12:11发布

我需要动态地创建一个类。 大多数事情做工精细,但我卡在产生的构造。

AssemblyBuilder _assemblyBuilder =
        AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyBuilder"),                                                        AssemblyBuilderAccess.Run);

ModuleBuilder _moduleBuilder = _assemblyBuilder.DefineDynamicModule("MyModule");

public static object GetInstance<TSource, TEventArgs>(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<MyClass, TSource, TEventArgs>
    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<GT, TEventSource, TEventArgs> : BaseClass
    where GT: GenericType<GT, TEventSource, TEventArgs>, new()
    where TEventArgs : EventArgs
    where TEventSource : class
{
    protected GenericType(string eventName)
    {
        _eventName = eventName;
    }
    // ...
}

我想有在运行时的结果:

public class MyType : BaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType>
{
    protected MyType() : base("SomeName")
    {

    }
}

Answer 1:

我认为问题是,你试图调用开放式泛型类型的构造GenericType<GT, TEventSource, TEventArgs>但你需要调用封闭式的构造函数BaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType> 该解决方案似乎很简单:

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

问题是,这并不工作,并抛出NotSupportedException 。 因此,它似乎得到一个泛型类型,其中的参数之一是的构造TypeBuilder是螺母的支持。

正因为如此,我认为使用Reflection.Emit的,除非有一些黑客来解决这一点,你想要什么是不可能的。

编辑:A-HA! 我不得不深入了解Reflection.Emit的在反射器(虽然看文档在正确的地方会工作过),但我发现它:有一种特殊的方法正是为了这一点: 静态TypeBuilder.GetConstructor() 所以这应该工作:

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


Answer 2:

要做到这一点,最简单的方法是将你的抽象类和派生类编译成一个简单的组装,然后使用可从一个插件的“Reflection.Emit的”语言反射器打开它们:

http://reflectoraddins.codeplex.com/

是的,因为它听起来这是为酷:)



文章来源: Dynamically create type and call constructor of base-class