2014-09-01 66 views
2

我正在使用Refletion.Emit,我有一個接口,一個抽象類和另一個類。我想要實現的是以這兩者爲基礎創建一個新班級。
所以這裏是一個簡單的界面:Reflection.Emit與泛型類型=類型不是通用的

public interface IHello() 
{  
    string SayHello(); 
} 

這是我的抽象類:

public abstract class Helloer<T> where T : IHello, new() 
{ 
     private readonly string text; 

     protected Helloer(string text) 
     { 
      this.text = text;     
     } 

     public string DoIt() 
     { 
      var t = new T(); 
      return t.SayHello() + text; 
     } 
} 

和第二類:

public class Howdy : IHello 
{ 
     public string SayHello() { return "Howdy"; } 
} 

現在,這是負責的全部主代碼創建新型HowdyHelloer:

public static void Run() 
    { 
     var type = CreateHelloer(typeof(Howdy)); 
     dynamic helloer = Activator.CreateInstance(type); 
     Console.WriteLine(helloer.DoIt()); 
    } 


    public static Type CreateHelloer(Type hello) 
    { 
     var assemblyBuilder = GetAssemblyBuilder("MyAssembly"); 
     var moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule"); 
     var typeBuilder = moduleBuilder.DefineType(hello.Name + "Helloer", TypeAttributes.Public); 
     var parentType = typeof(Helloer<>).MakeGenericType(hello); 

     typeBuilder.SetParent(parentType); 
     Type[] types = new Type[1]; 
     types[0] = typeof(string); 
     var parentCtorGeneric1 = typeof(Helloer<>).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, types, null); 


     var parentCtor = TypeBuilder.GetConstructor(parentType, parentCtorGeneric1); 
     var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { }); 
     var ctorIl = ctor.GetILGenerator(); 
     ctorIl.Emit(OpCodes.Ldstr, "Partner"); 
     ctorIl.Emit(OpCodes.Call, parentCtor); 
     ctorIl.Emit(OpCodes.Ret); 

     return typeBuilder.CreateType(); 
    } 

    public static AssemblyBuilder GetAssemblyBuilder(string name) 
    { 
     var assemblyName = new AssemblyName(name); 
     var domain = AppDomain.CurrentDomain; 
     AssemblyBuilder c = domain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 
     return c; 
    } 

就行了:

var parentCtor = TypeBuilder.GetConstructor(parentType, parentCtorGeneric1); 

我得到一個錯誤:「‘類型’必須包含TypeBuilder作爲一個通用的說法。」 任何人都可以幫助我嗎?正如我在最近3天試圖解決這個問題一樣:我做了研究,說實話,我沒有發現任何關於使用Emit和泛型抽象類的具體內容。

+0

你用這行做了什麼'var parentCtor = TypeBuilder.GetConstructor(parentType,parentCtorGeneric1);'?在[msdn TypeBuilder.GetConstructor方法](http://msdn.microsoft.com/en-us/library/ms145822(v = vs.110).aspx)_構造函數被返回的構造泛型類型__但您嘗試通過沒有構造類型 – Grundy 2014-09-01 12:18:29

+0

無論如何你錯了爲創建類型創建構造函數 – Grundy 2014-09-01 12:28:50

+0

那麼你能告訴我/解釋這應該如何正確完成? – Eru 2014-09-01 12:36:03

回答

3

我在你的代碼至少兩個錯誤

首先看到:

var parentCtor = TypeBuilder.GetConstructor(parentType, parentCtorGeneric1); 

這裏parentType不是用TypeBuilder創建的,所以如果你想獲得父母constuctor剛剛從父類型得到它像

var parentCtorGeneric1 = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, types, null); 

第二:你錯了創建的聯合代碼,應該是這樣的

var ctorIl = ctor.GetILGenerator(); 
ctorIl.Emit(OpCodes.Ldarg_0); // show where to load the following string 
ctorIl.Emit(OpCodes.Ldstr, "Partner"); 
ctorIl.Emit(OpCodes.Call, parentCtorGeneric1); 
ctorIl.Emit(OpCodes.Ret); 
+0

好:)謝謝sooooo! – Eru 2014-09-01 12:46:07