【问题标题】:Event Interception with Castle DynamicProxy使用 Castle DynamicProxy 进行事件拦截
【发布时间】:2023-03-03 04:33:02
【问题描述】:

在谷歌搜索中,我似乎找不到在代理类型上拦截事件的示例,而且它似乎对我不起作用。有没有办法可以做到这一点(即在调用事件时使用 IInterceptor)?

【问题讨论】:

    标签: events castle-windsor castle-dynamicproxy


    【解决方案1】:

    我对此表示怀疑。 Castle Dynamic Proxy 通过拦截在代理上进行的调用来工作。事件不在代理上进行。它们是由 .NET 框架处理的回调。

    【讨论】:

    • 没错。使用 DP 可以拦截方法,包括事件订阅和取消订阅,仅此而已。
    • 谢谢,我下面的解决方案完成了我一直在寻找的,所以这不是必需的。
    【解决方案2】:

    我最终使用了 ComponentCreated 事件,然后添加了一个带有 DynamicMethod 的动态事件处理程序来完成我想要的:

    private static readonly MethodInfo internalPublishEventMethod =
        typeof(EventPublisher).GetMethod("PublishEvent", BindingFlags.Static | BindingFlags.NonPublic);
    
    private void Container_ComponentCreated(global::Castle.Core.ComponentModel model, object instance)
    {
        if (instance != null)
        {
            Type type = instance.GetType();
    
            var eventPublisherAttribute = type.GetAttribute<EventPublisherAttribute>();
    
            if (eventPublisherAttribute != null)
            {
                foreach (EventInfo ei in type.GetEvents())
                {
                    if (eventPublisherAttribute.PublishAllEvents || ei.GetCustomAttributes(typeof(PublishedEventAttribute), false).Length > 0)
                    {
                        // emit an event handler
    
                        MethodInfo invoke = ei.EventHandlerType.GetMethod("Invoke");
                        Type[] parameters = invoke.GetParameters().Select(p => p.ParameterType).ToArray();
    
                        var method = new DynamicMethod(string.Empty, null, parameters, instance.GetType(),
                                                       true);
                        ILGenerator generator = method.GetILGenerator();
                        // sender
                        generator.Emit(OpCodes.Ldarg_0);
                        // args
                        generator.Emit(OpCodes.Ldarg_1);
                        // topic
                        generator.Emit(OpCodes.Ldstr, ei.Name);
                        generator.Emit(OpCodes.Call, internalPublishEventMethod);
                        generator.Emit(OpCodes.Ret);
    
                        Delegate d = method.CreateDelegate(ei.EventHandlerType);
                        ei.AddEventHandler(instance, d);
                    }
                }
            }
        }
    }
    
    private static void PublishEvent(object sender, EventArgs e, string topic)
    {
        if (e != null)
        {
        // do stuff
        }
    }
    

    【讨论】:

    猜你喜欢
    • 2011-04-26
    • 2012-03-31
    • 2018-06-23
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 2019-02-15
    相关资源
    最近更新 更多