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

时间:2012-04-10 14:07:19

标签: c# reflection reflection.emit ilgenerator

我需要动态创建一个类。大多数工作都很好,但我一直在生成构造函数。

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")
    {

    }
}

2 个答案:

答案 0 :(得分:11)

我认为问题在于您尝试调用开放泛型类型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!我不得不深入研究Reflector 中的Reflection.Emit(尽管在文档中查找正确的位置也会有效) ,但我发现它:有一个特殊的完全是这样的方法:the static TypeBuilder.GetConstructor()。所以这应该有效:

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

答案 1 :(得分:4)

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

http://reflectoraddins.codeplex.com/

Reflector: Reflection.Emit language

是的,这听起来很酷:)