2014-09-01 6 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 Method] (http://msdn.microsoft.com/en-us/library/ms145822 (v = vs.110) .aspx) _ Созданный общий тип, конструктор которого возвращается. но вы пытаетесь пройти нестроенный тип – Grundy

+0

в любом случае вы ошиблись создать конструктор для созданного типа – Grundy

+0

Можете ли вы затем рассказать мне/объяснить, как это должно быть сделано правильно? – Eru

ответ

3

я вижу в вашем коде, по крайней мере две ошибки

первый:

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

здесь parentType не была создана с TypeBuilder, так что если вы хотите получить родитель constuctor просто получить его от родительского типа, как

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

second: вы ошиблись, создайте код кондуктора, ему должно понравиться

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

Смежные вопросы