2011-03-11 21 views
8

Próbowałem zdefiniować typ w czasie wykonywania, który dziedziczy po znanej klasie i implementuje interfejs.Implementowanie interfejsu w czasie wykonywania: metoda get_Value nie zaimplementowana

public class ParentClass 
{ 
} 

public interface IImplementMe 
{ 
    double Value{get;set} 
} 

Oto fragment kodu, który pokazuje, w jaki sposób staram się osiągnąć mój cel.

public class ClassBuilder 
    { 
    public Type Build() 
    { 
     try 
     { 
      AssemblyName assemblyName = new AssemblyName("DataBuilderAssembly"); 
      AssemblyBuilder assemBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 
      ModuleBuilder moduleBuilder = assemBuilder.DefineDynamicModule("DataBuilderModule"); 
      TypeBuilder typeBuilder = moduleBuilder.DefineType("NewClass", TypeAttributes.Class, typeof(ParentClass)); 
      typeBuilder.AddInterfaceImplementation(typeof(IImplementMe)); 
      BuildProperty(typeBuilder, "Value", typeof(double)); 
      Type type = typeBuilder.CreateType(); 

      return type; 
     } 
     catch (Exception e) 
     { 
      return null; 
     } 

    } 

    private void BuildProperty(TypeBuilder typeBuilder, string name, Type type) 
    { 
     FieldBuilder field = typeBuilder.DefineField("m" + name, type, FieldAttributes.Private); 
     PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(name, PropertyAttributes.None, type, null); 

     MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig; 

     MethodBuilder getter = typeBuilder.DefineMethod("get_" + name, getSetAttr, type, Type.EmptyTypes); 

     ILGenerator getIL = getter.GetILGenerator(); 
     getIL.Emit(OpCodes.Ldarg_0); 
     getIL.Emit(OpCodes.Ldfld, field); 
     getIL.Emit(OpCodes.Ret); 

     MethodBuilder setter = typeBuilder.DefineMethod("set_" + name, getSetAttr, null, new Type[] { type }); 

     ILGenerator setIL = setter.GetILGenerator(); 
     setIL.Emit(OpCodes.Ldarg_0); 
     setIL.Emit(OpCodes.Ldarg_1); 
     setIL.Emit(OpCodes.Stfld, field); 
     setIL.Emit(OpCodes.Ret); 


     propertyBuilder.SetGetMethod(getter); 
     propertyBuilder.SetSetMethod(setter); 
    } 
} 

Z jakiegoś powodu otrzymuję „metoda get_Value nie realizowany” wyjątku na wywołanie typeBuilder.CreateType(). Do tej pory nie widziałem powodu, który za tym stoi.

Odpowiedz

7

Zmiana wiersz:

MethodAttributes getSetAttr = MethodAttributes.Public | 
    MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual; 

Twój kod następnie pracował dla mnie. (Wymagane było wirtualne.)

+0

Próbowano dodać "MethodAttributes.SpecialName", ale to nie pomogło. :/ –

+0

@ L.E.O., Próbowałem twój kod sam, i to działało dobrze, gdy dodałem wszystkie atrybuty metody, o których wspomniałem (wirtualny wydaje się być wymagany). –

+0

Tak, dziękuję, działał jak czar. –

12

Implementacja niejawnego interfejsu C# (według nazwy) jest jedynie wygodą; robiąc to ręcznie, należy powiązać każdą z nich w tabeli metod wirtualnych za pomocą metody typeBuilder.DefineMethodOverride, przekazując nową (wygenerowaną) metodę i metodę interfejsu, aby spełnić wymagania. To musi być zrobione dla każdej metody każdego interfejsu, który chcesz zaimplementować.

+0

To coś, o czym będę świadomy. Dzięki. –

Powiązane problemy