在带有事件的动态类型上实现接口 [英] Implementing an Interface on a dynamic type with events

查看:96
本文介绍了在带有事件的动态类型上实现接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个接口,循环遍历.GetEvents()返回数组,并尝试在我的动态类型上实现该事件。当我尝试调用TypeBuilder.CreateType()时,遇到了这个可爱的错误:

I am taking in an interface, looping through the .GetEvents() return array and attempting to implement the event on my dynamic type. At the point when I try to call TypeBuilder.CreateType(), I am greeted with this lovely error:

来自程序集类型的应用程序方法将覆盖具有以下内容的方法:被覆盖。

"Application method on type from assembly is overriding a method that has been overridden."

如果我注释掉尝试实现接口方法的typeBuilder.DefineMethodOverride调用,则当我尝试订阅该事件时,就会收到提示。错误:

If I comment out the typeBuilder.DefineMethodOverride calls that attempt to implement the interface methods, at the poin when I attempt to subscribe to the event I get the error:

该方法或操作未实现。

"The method or operation is not implemented."

这是我拥有的方法尝试将检测到的事件添加到发出的类型。简要说明一下,我还有其他代码定义了类型并添加了在接口上实现这些方法的方法,所有这些代码都可以正常工作。在尝试将事件添加到组合中之前,我没有任何问题。

Here is the method I have that is attempting to add the detected event to the emitted type. Just a quick note, I have other code defining the type and adding methods implementing those on the interface and all that code works fine. I had no problems until I attempted to add events into the mix.

protected static void AddEvent(EventInfo interfaceEvent, TypeBuilder proxyBuilder)
    {
        // Event methods attributes
        MethodAttributes eventMethodAttr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName;
        MethodImplAttributes eventMethodImpAtr = MethodImplAttributes.Managed | MethodImplAttributes.Synchronized;

        string qualifiedEventName = string.Format("{0}.{1}", typeof(T).Name, interfaceEvent.Name);
        string addMethodName = string.Format("add_{0}", interfaceEvent.Name);
        string remMethodName = string.Format("remove_{0}", interfaceEvent.Name);

        FieldBuilder eFieldBuilder = proxyBuilder.DefineField(qualifiedEventName,
            interfaceEvent.EventHandlerType, FieldAttributes.Public);

        EventBuilder eBuilder = proxyBuilder.DefineEvent(qualifiedEventName, EventAttributes.None, interfaceEvent.EventHandlerType);

        // ADD method
        MethodBuilder addMethodBuilder = proxyBuilder.DefineMethod(addMethodName,
            eventMethodAttr, null, new Type[] { interfaceEvent.EventHandlerType });

        addMethodBuilder.SetImplementationFlags(eventMethodImpAtr);

        // We need the 'Combine' method from the Delegate type
        MethodInfo combineInfo = typeof(Delegate).GetMethod("Combine", new Type[] { typeof(Delegate), typeof(Delegate) });

        // Code generation
        ILGenerator ilgen = addMethodBuilder.GetILGenerator();
        ilgen.Emit(OpCodes.Ldarg_0);
        ilgen.Emit(OpCodes.Ldarg_0);
        ilgen.Emit(OpCodes.Ldfld, eFieldBuilder);
        ilgen.Emit(OpCodes.Ldarg_1);                    
        ilgen.Emit(OpCodes.Call, combineInfo);            
        ilgen.Emit(OpCodes.Castclass, interfaceEvent.EventHandlerType);    
        ilgen.Emit(OpCodes.Stfld, eFieldBuilder);  
        ilgen.Emit(OpCodes.Ret);

        // REMOVE method
        MethodBuilder removeMethodBuilder = proxyBuilder.DefineMethod(remMethodName,
            eventMethodAttr, null, new Type[] { interfaceEvent.EventHandlerType });
        removeMethodBuilder.SetImplementationFlags(eventMethodImpAtr);

        MethodInfo removeInfo = typeof(Delegate).GetMethod("Remove", new Type[] { typeof(Delegate), typeof(Delegate) });

        // Code generation
        ilgen = removeMethodBuilder.GetILGenerator();
        ilgen.Emit(OpCodes.Ldarg_0);
        ilgen.Emit(OpCodes.Ldarg_0);
        ilgen.Emit(OpCodes.Ldfld, eFieldBuilder);    
        ilgen.Emit(OpCodes.Ldarg_1);                 
        ilgen.Emit(OpCodes.Call, removeInfo);            
        ilgen.Emit(OpCodes.Castclass, interfaceEvent.EventHandlerType);   
        ilgen.Emit(OpCodes.Stfld, eFieldBuilder);  
        ilgen.Emit(OpCodes.Ret);

        // Finally, setting the AddOn and RemoveOn methods for our event
        eBuilder.SetAddOnMethod(addMethodBuilder);
        eBuilder.SetRemoveOnMethod(removeMethodBuilder);

        // Implement the method from the interface
        proxyBuilder.DefineMethodOverride(addMethodBuilder, typeof(T).GetMethod("add_" + interfaceEvent.Name));

        // Implement the method from the interface
        proxyBuilder.DefineMethodOverride(removeMethodBuilder, typeof(T).GetMethod("remove_" + interfaceEvent.Name));

    }

Google对此提供了0帮助(搜索是覆盖已被覆盖的方法只会返回很多Crystal Reports主题),而我整个上午一直在苦苦挣扎。

Google has been 0 help on this (searching for "is overriding a method that has been overridden" just returns a lot of Crystal Reports topics), and I have been struggling with this all morning. Any help would be greatly appreciated!

推荐答案

没关系。当我遍历接口的方法来实现它们时,我不小心也实现了添加/删除。

Nevermind. When i loop through the method's of the interface to implement them I am accidentally implementing the add/remove also.

在我的循环中对此进行了修复: if(method.IsSpecialName)继续;

fixed it with this in my loop: if(method.IsSpecialName) continue;

这篇关于在带有事件的动态类型上实现接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆