运行时实现接口:get_Value 方法未实现

问题描述 投票:0回答:3

我试图在运行时定义一个继承自已知类并实现接口的类型。

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

出于某种原因,我在调用

typeBuilder.CreateType()
时收到“get_Value 方法未实现”异常。到目前为止还看不出背后的原因。

c# reflection types runtime definition
3个回答
14
投票

C# 隐式接口实现(通过名称匹配)只是为了方便;手动执行时,您需要使用 typeBuilder.DefineMethodOverride 将虚拟方法表中的每个关联起来,传入新的(生成的)方法和接口方法以满足。必须为您要实现的每个接口的每个方法完成此操作。


12
投票

将您的线路更改为:

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

你的代码对我有用。 (需要虚拟。)


0
投票

需要将其标记为虚拟的,并将实现显式绑定到接口:

                // Associate the methods with the interface
                foreach (var interfaceType in typeBuilder.ImplementedInterfaces)
                {
                    var getMethod = interfaceType.GetMethod($"get_{fieldName}");
                    var setMethod = interfaceType.GetMethod($"set_{fieldName}");

                    if (getMethod != null)
                    {
                        typeBuilder.DefineMethodOverride(
                            getterBuilder,
                            getMethod);
                    }

                    if (setMethod != null)
                    {
                        typeBuilder.DefineMethodOverride(
                            setterBuilder,
                            setMethod);
                    }
                }
© www.soinside.com 2019 - 2024. All rights reserved.