2012-04-10 8 views
10

動的にクラスを作成する必要があります。ほとんどのものは正常に動作しますが、私はコンストラクタを生成することに固執しています。ベースクラスの型と呼び出しコンストラクタを動的に作成

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を取得しています。何が間違っているのですか?

要求通り:私は、問題があることだと思う

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

    } 
} 
+0

は見てくださいここhttp://stackoverflow.com/questions/893423/how-do-create-a-dynamic-class-in-c-sharp-4 –

+0

本当に役に立たなかったか、何か迷ったのですか?私はベースクラスを継承し、引数を持つベースコンストラクタと呼んでいます。 – SACO

+0

このリンクも試してみてくださいhttp://blogs.msdn.com/b/cburrows/archive/2009/04/22/dynamic-base-classes-in-c-4.aspx –

答えて

10

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; 
    } 
    // ... 
} 

を私は、実行時に結果として持っていたいと思い何オープンジェネリックタイプGenericType<GT, TEventSource, TEventArgs>のコンストラクタを呼び出そうとしていますが、クローズドタイプBaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType>のコンストラクタを呼び出す必要があります。解決策は簡単なようだ:

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

問題は、これが動作しないということであるとNotSupportedExceptionをスローします。したがって、ジェネリック型のコンストラクタが得られるようです。パラメータの1つがTypeBuilderでナットがサポートされています。

このため、この問題を回避するためにいくつかのハックがない限り、Reflection.Emitを使用して、あなたが望むものはできないと思います。

編集: A-HA!私はReflectorに深入りしなければなりませんでした。が見つかりましたが、私はそれを見つけました。これには特別な方法があります:the static TypeBuilder.GetConstructor()。だから、これは動作するはずです:

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

だから私はハックを楽しみにしています:) – SACO

+0

実際、それはまったくハックではありません。編集を参照してください。 – svick

+0

ところで、このような私に新しいものを学ばせるような質問は最高です。 – svick

3

、その後、簡単な組み立てにあなたの抽象と派生クラスをコンパイルアドインとして利用できる「Reflection.Emit」言語を使用してリフレクターでそれらを開くことになり、これを行うための最も簡単な方法From:

http://reflectoraddins.codeplex.com/

Reflector: Reflection.Emit language

はい、それはそれは思ったほどクールだ:)

+0

この特定のケースではうまくいくと思いますか? – svick

+0

希望のクラス定義が有効なC#でコンパイルされている場合はyesです。 – x0n

+0

このケースで生成されるコードはあまり意味がなく、OPを助けません。これは 'typeof(MyType)'を使用しているためです。これは、その型を構築するときに意味をなさないものです。代わりに 'typeBuilder'を使用すると' NotSupportedException'が発生します。 – svick

関連する問題