问题:
在我的域层组件中我存储了两个接口:
public interface IDomainEvent { }
和
public interface IHandle<T> where T: IDomainEvent, new()
EventDispatcher
类也定义在那里:
public static class EventDispatcher {
[ThreadStatic]
private static List<Delegate> actions;
[ThreadStatic]
private static List<Object> handlers;
public static List<Object> Handlers {
get { return handlers; }
set { handlers = value; }
}
public static void Register<T>(Action<T> callback) where T : IDomainEvent, new() {
if(null == actions) {
actions = new List<Delegate>();
actions.Add(callback);
}
}
public static void ClearCallbacks() {
actions = null;
}
public static void Raise<T>(T @event) where T : IDomainEvent, new() {
if(null != Handlers) {
foreach(var handler in Handlers.Where(h => h is IHandle<T>)) {
((IHandle<T>)handler).Handle(@event);
}
}
if(null != actions) {
foreach(var action in actions) {
if(action is Action<T>) {
((Action<T>)action)(@event);
}
}
} // if(null != actions) {
}
}
表示层汇编中有一个模块:
public class EventDispatchingModule : NinjectModule {
public override void Load() {
// EventDispatcher.Handlers = this.Kernel.GetAll(IHandle<T>); Can't do that!
// Bind<IHandle<CarHasBeenRegisteredEvent>>().To<CarHasBeenRegisteredHandler();
}
}
所以我无法在那里拨打Kernel.GetAll(IHandle<T>)
,因为它无法解析T
参数。
我如何解决这个问题?
谢谢!
答案 0 :(得分:2)
无需使用模块(我没有使用过ninject,但类似的东西):
// Put these in the domain project
public class EventDispatcher
{
private static IEventDispatcher _dispatcher;
public static void Setup(IEventDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public static void Dispatch<T>(T domainEvent) where T : IDomainEvent
{
_dispatcher.Dispatch<T>(domainEvent);
}
}
public interface IEventDispatcher
{
public void Dispatch<T>(T domainEvent) where T : IDomainEvent;
}
// and this one in the project which has Ninject
public class NinjectEventDispatcher : IEventDispatcher
{
private static IKernel _container;
public NinjectEventDispatcher(IKernel container)
{
_container = container;
}
public void Dispatch<T>(T domainEvent) where T : IDomainEvent
{
foreach (var listener in _container.GetAll<IHandle<T>>())
{
listener.Handle(domainEvent);
}
}
}
// And after the container have been configured:
EventDispatcher.Setup(new NinjectEventDispatcher(_container));
但我不知道ninject如何处理范围对象(也可能想要接收事件)。
我的容器内置了域事件,请参阅本文:http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
<强>更新强>
我已更新代码示例,以使域项目不知道Ninject。
您没有使用此代码的服务位置。事件调度员的内部是。即你的代码都没有受到它的影响。
答案 1 :(得分:2)
您可以使用以下代码获取所有处理程序
Kernel.GetAll(typeof (IHandle<>));
但无论如何,在NInjectModule中加载所有IHanders并不是一个好主意,因为您不知道是否已经加载了其他模块(而另一个模块也可以注册Handler)。 我建议使EventDispatcher类不是静态的,并在你需要的范围内注册它(如果你需要为每个请求新的处理程序 - 在请求范围内,否则 - 在单例范围内。你可以使用构造函数注入的处理程序如下:
Kerner.Bind<EventDispatcher>().ToSelf()
.InRequestScope()
.WithConstructorArgument("handlers", c => c.Kernel.GetAll(typeof(IHandler<>)))
希望这有帮助