2011-03-11 10 views
8

Stavo cercando di definire un tipo in fase di esecuzione che erediti da una classe conosciuta e implementa un'interfaccia.Implementazione dell'interfaccia in fase di esecuzione: metodo get_Value non implementato

public class ParentClass 
{ 
} 

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

Ecco lo snippet di codice che mostra come cerco di raggiungere il mio obiettivo.

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); 
    } 
} 

Per qualche motivo ricevo un "metodo di Get_Value non implementato" eccezione a chiamare typeBuilder.CreateType(). Finora non è stato in grado di vederne il motivo.

risposta

7

Modifica della linea:

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

Il codice poi lavorato per me. (Il virtual era richiesto.)

+0

Provato aggiungendo "MethodAttributes.SpecialName", ma quello non ha aiutato. :/ –

+0

@ L.E.O., Ho provato il tuo codice da solo, e ha funzionato bene quando ho aggiunto tutti gli attributi del metodo che ho menzionato (virtuale sembra essere stato richiesto). –

+0

Sì, grazie, ha funzionato come un fascino. –

12

L'implementazione dell'interfaccia implicita C# (per corrispondenza del nome) è solo conveniente; quando lo si fa a mano è necessario associare ciascuno nella tabella del metodo virtuale usando typeBuilder.DefineMethodOverride, passando il nuovo metodo (generato) e il metodo di interfaccia da soddisfare. Questo deve essere fatto per ogni metodo di ogni interfaccia che vuoi implementare.

+0

Questo è qualcosa di cui sarò a conoscenza. Grazie. –

Problemi correlati