【问题标题】:Castle DynamicProxy breaks EventWiring ListenersCastle DynamicProxy 中断 EventWiring 监听器
【发布时间】:2014-06-20 23:38:53
【问题描述】:

故事是这样开始的,我使用 Castle EventWiring 工具在我的类中定义事件的侦听器,它工作得很好,我曾经像这样引发事件:

if (null != BlaBlaEvent)
{
    BlaBlaEvent(someData);
}

最近我遇到一个业务需求,并认为最好的解决方案可能是使用代理模式,所以我使用了 DynamicProxy,在我的 IoC 解析功能(Castle Windsor 的一个小包装器)中,我有以下代码:

T componenet = _container.Resolve<T>();

var gen = new ProxyGenerator();

if (typeof(T).IsClass)
{
    return gen.CreateClassProxyWithTarget(componenet, _container.Resolve<StashInterceptor>());
}
else
{
    return gen.CreateInterfaceProxyWithTarget(componenet, _container.Resolve<StashInterceptor>());
}

这也有效,它不是返回一个具体类,而是返回一个代理,该代理拦截函数调用并进行一些处理,然后将调用转发给原始的具体类方法。

现在的问题是具体类中的事件没有侦听器(即使配置说明它们有)。

不确定这是错误还是设计决定在从代理调用方法时不加载侦听器,但目前我很困惑,需要解决方案或解决方法。

有人有想法吗?

这是我在 web.config 中的城堡 xml 配置:

<castle>
    <facilities>
        <facility id="event.wiring" type="Castle.Facilities.EventWiring.EventWiringFacility, Castle.Facilities.EventWiring" />
    </facilities>
<components>
  <component id="SomeInterceptor" type="Namespace.SomeInterceptor, MyAssembly" />

  <component id="SomePublisher" type="Namespace.SomePublisher, MyAssembly">
    <subscribers>
      <subscriber id="SomeSubscriber" event="SomeEvent" handler="OnSomeEvent" />
    </subscribers>
  </component>
  <component id="SomeSubscriber" type="Namespace.SomeSubscriber, MyAssembly" />
</components>

【问题讨论】:

    标签: c# castle-windsor castle castle-dynamicproxy


    【解决方案1】:

    注意:问题不在于 xml 或流畅的配置,而是您自己通过 Castle.DynamicProxy 生成代理的事实。如果您改为利用容器并使用容器中的功能注册拦截器(顺便说一下,它使用 DynamicProxy),这将起作用。

    不确定您到底想做什么,但如下所示,向侦听器注册拦截器并让它拦截侦听器方法调用并同时使用事件连接功能不是问题。这是温莎3.3

    public class EventWiringFacilityTests
    {
        public void RegisterInterceptorWithListenerAndMakeSureListenerSubscribes()
        {
            var container = new WindsorContainer();
    
            container.AddFacility<EventWiringFacility>();
    
            container.Register(Component.For<SomeInterceptor>());
    
            container.Register(
               Component.For<SimplePublisher>()
                  .PublishEvent(p => p.Event += null,
                                x => x.To<SimpleListener>("foo", l => l.OnEvent(null, null))),
               Component.For<SimpleListener>().Interceptors<SomeInterceptor>().Named("foo"));
    
            var someInterceptor = container.Resolve<SomeInterceptor>();
    
            var simpleListener = container.Resolve<SimpleListener>();
            Assert.That(simpleListener.EventHasHappened, Is.False);
    
            var simplePublisher = container.Resolve<SimplePublisher>();
            simplePublisher.Trigger();
    
            Assert.That(simpleListener.EventHasHappened);
    
            simpleListener.Snap();
            Assert.That(someInterceptor.Intercepted);
        }
    }
    
    public class SomeInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            Intercepted = true;
            invocation.Proceed();
        }
    
        public bool Intercepted { get; set; }
    }
    
    public class SimplePublisher
    {
        public event EventHandler Event;
    
        public void Trigger()
        {
            if (Event != null)
            {
                Event(this, new EventArgs());
            }
        }
    }
    
    public class SimpleListener
    {
        public bool EventHasHappened { get; set; }
    
        public void OnEvent(object sender, EventArgs e)
        {
            EventHasHappened = true;
        }
    
        public virtual void Snap()
        {
    
        }
    }
    

    【讨论】:

    • 感谢您的回复,但它似乎不适用于我,我使用 xml 映射,我将编辑问题以向您展示我的配置。
    猜你喜欢
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    • 1970-01-01
    相关资源
    最近更新 更多