Реализация интерфейса на динамическом типе с событиями - PullRequest
1 голос
/ 15 апреля 2009

Я использую интерфейс, перебираю возвращаемый массив .GetEvents () и пытаюсь реализовать событие для моего динамического типа. В тот момент, когда я пытаюсь вызвать TypeBuilder.CreateType (), я приветствую эту прекрасную ошибку:

"Метод приложения для типа из сборки переопределяет метод, который был переопределен."

Если я закомментирую вызовы typeBuilder.DefineMethodOverride, которые пытаются реализовать методы интерфейса, в точке, когда я пытаюсь подписаться на событие, я получаю сообщение об ошибке:

"Метод или операция не реализованы."

Вот метод, который у меня есть, который пытается добавить обнаруженное событие к выданному типу. Просто короткое замечание, у меня есть другой код, определяющий тип и добавляющий методы, реализующие методы интерфейса, и весь этот код работает нормально. У меня не было проблем, пока я не попытался добавить события в микс.

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 уже помогал по этому вопросу (поиск "переопределяет метод, который был переопределен", просто возвращает много тем Crystal Reports), и я боролся с этим все утро. Любая помощь будет очень ценится!

1 Ответ

1 голос
/ 15 апреля 2009

Nevermind. Когда я перебираю методы интерфейса для их реализации, я также случайно добавляю / удаляю.

исправил это в моем цикле: if(method.IsSpecialName) continue;

...