Реализация интерфейса во время выполнения: метод get_Value не реализован - PullRequest
12 голосов
/ 11 марта 2011

Я пытался определить тип во время выполнения, который наследуется от известного класса и реализует интерфейс.

public class ParentClass
{
}

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

Вот фрагмент кода, который показывает, как я пытаюсь достичь своей цели.

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

По какой-то причине я получаю исключение "метод get_Value не реализован" при вызове typeBuilder.CreateType().Пока что не вижу причины этого.

Ответы [ 2 ]

13 голосов
/ 11 марта 2011

Неявная реализация интерфейса c # (по совпадению имен) только для удобства;когда вы делаете это вручную, вам нужно связать каждый из них в таблице виртуальных методов, используя typeBuilder.DefineMethodOverride, передавая новый (сгенерированный) метод и метод интерфейса для удовлетворения.Это должно быть сделано для каждого метода каждого интерфейса, который вы хотите реализовать.

10 голосов
/ 11 марта 2011

Изменение вашей линии на:

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

Ваш код работал на меня. (Требовался виртуал.)

...