2011-03-11 23 views
8

Estaba tratando de definir un tipo en tiempo de ejecución que hereda de una clase conocida e implementa una interfaz.Implementación de la interfaz en tiempo de ejecución: método get_Value no implementado

public class ParentClass 
{ 
} 

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

Aquí está el fragmento de código que muestra cómo trato de lograr mi objetivo.

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

Por alguna razón, me sale un "método Get_Value no implementado" excepción en llamar typeBuilder.CreateType(). Hasta ahora no ha podido ver la razón detrás de esto.

Respuesta

7

Cambio de la línea a:

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

Su código de entonces trabajó para mí. (Se requiere lo virtual.)

+0

Intentó agregar 'MethodAttributes.SpecialName', pero eso no ayudó. :/ –

+0

@ L.E.O., Probé su código yo mismo, y funcionó bien cuando agregué todos los atributos de método que mencioné (parece que se requiere virtual). –

+0

Sí, gracias, funcionó como un amuleto. –

12

La implementación de la interfaz implícita C# (por coincidencia de nombre) es solo de conveniencia; cuando lo haces a mano necesitas asociar cada uno en la tabla de métodos virtuales usando typeBuilder.DefineMethodOverride, pasando el método nuevo (generado) y el método de interfaz para satisfacer. Esto debe hacerse para cada método de cada interfaz que desee implementar.

+0

Eso es algo de lo que tendré conocimiento. Gracias. –

Cuestiones relacionadas