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

发布于 2024-10-21 08:24:05 字数 2180 浏览 1 评论 0原文

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

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 方法未实现”异常。目前还看不出其背后的原因。

I was trying to define a type at run-time that inherits from a known class and implements an interface.

public class ParentClass
{
}

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

Here's the code snippet that shows how I try to achieve my goal.

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

For some reason I get an "get_Value method not implemented" exception on calling typeBuilder.CreateType(). So far unable to see the reason behind it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回眸一笑 2024-10-28 08:24:05

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

The c# implicit interface implementation (by name match) is convenience only; when doing it by hand you need to associate each in the virtual-method table using typeBuilder.DefineMethodOverride, passing in the new (generated) method and the interface method to satisfy. This must done for each method of every interface you want to implement.

花想c 2024-10-28 08:24:05

将您的行更改为:

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

然后您的代码对我有用。 (需要虚拟。)

Changing your line to:

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

Your code then worked for me. (The virtual was required.)

空心↖ 2024-10-28 08:24:05

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

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

You need to mark it as virtual, and explicitly bind the implementation to the interface:

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

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

                    if (setMethod != null)
                    {
                        typeBuilder.DefineMethodOverride(
                            setterBuilder,
                            setMethod);
                    }
                }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文