故事以这种方式开始,我使用了Castle EventWiring工具来定义类中事件的侦听器,并且效果很好,我曾经引发过这样的事件:
if (null != BlaBlaEvent)
{
BlaBlaEvent(someData);
}
最近,我遇到一个业务需求,并认为最好的解决方案可能是使用代理模式,因此我在我的IoC解析功能(Castle Windsor的一个小型包装器)中使用了DynamicProxy,我有以下代码:
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>());
}
这也行得通,而不是返回具体的类,而是返回一个代理,该代理拦截函数调用并进行一些处理,然后将调用转发给原始的具体类方法.
现在的问题是,具体类中的事件没有侦听器(即使配置表明确实有侦听器).
不知道这是Bug还是设计决定,不从代理调用方法时不加载侦听器,但目前我处在困境中,需要解决方案或解决方法.
有人有主意吗?
这是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>
解决方法:
注意:问题不是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()
{
}
}