我在最近的项目中实现事件处理时遇到了困难。
我已验证 structuremap 正在正确扫描、组装和添加 EventHandlers
Scan(cfg =>
{
cfg.TheCallingAssembly();
cfg.IncludeNamespace("ABC.EventHandler");
cfg.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
});
public class StructureMapEventDispatcher : IEventDispatcher
{
public void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent
{
foreach (var handler in ObjectFactory.GetAllInstances<IHandle<TEvent>>())
{
handler.Handle(eventToDispatch);
}
}
}
之前我曾经从域中触发事件。类似 Dispatcher.RaiseEvent(new [domainEvent class](x,y,z));
的东西
事件将被触发。我不得不更改我现在在集合中收集事件的设计
_domainEvents = new Collection<IDomainEvent>();
然后在我将域保存到存储库后提升它
public static void Raise(ICollection<IDomainEvent> domainEvents)
{
foreach (var domainEvent in domainEvents)
{
DomainEventDispatcher.Raise(domainEvent);
}
}
但是现在
ObjectFactory.GetAllInstances<IHandle<TEvent>>()
返回 0 个处理程序
如果我看
ObjectFactory.GetAllInstances<IHandle<DomainEventClass>>()
它正确返回处理程序集合(目前我有 2 个,它显示 2 个计数)
...我假设这与类型 IDomainEvent
引发的事件有关而不是实际类型,这使得结构图很难解析它。
我该如何解决这个问题?
问候,
三月
--
编辑 1:
我确认 structuremap 容器包含从程序集扫描的所有事件处理程序。
编辑 2
我不知道如何让这个问题吸引更多的关注。我正在为实现所需结果的解决方案增加赏金。如果问题不清楚,请提问。
基本上我想要 ObjectFactory.GetAllInstances<IHandle<TEvent>>()
返回 TEvent
的处理程序其中 TEvent
类型为 IDomainEvent
.要引发的事件存储在 IDomainEvent
的集合中并在域被保存(从服务层)之后引发。
我认为应该有一些方法可以让 structuremap 知道引发的事件为 IDomainEvent
实际上是类型 DomainEvent
var eventsToRaise= dealer.EventsToRaise(); 从调试窗口添加信息:
在调度程序窗口中引发事件之后
编辑 3:
尽管 eventToRaise 显示为“DealerName Changed”和“DealerCommunicationChanged”
typeof(TEvent) 给出 Type 作为 Domain.IDomainEvent
我猜想如果能够转换为正确的类型(从 VS 监 window 口获取信息的任何地方),问题就可以得到解决
----- 结果---
这两种方法都奏效了。我将这两个方法都交给了我团队中的其他 2 名成员,我们认为没有经过深思熟虑的解决方案被选为正确答案。
今天我们将对更改后的实现进行测试,看看解决方案中是否存在此解决方案的问题。
我赞成基于反射的解决方案,因为它也是正确的答案。
最佳答案
如您所说,问题是您要为 IHandle<IDomainEvent>
的所有实例询问结构图它没有这些,structuremap 有具体事件的处理程序。您需要使用事件的实际类型构造类型,然后请求该事件的所有处理程序:
Type genericHandler = typeof(IHandle<>);
Type[] typeArgs = { eventToDispatch.GetType() };
Type neededHandler = genericHandler.MakeGenericType(typeArgs);
var handlers = ObjectFactory.GetAllInstances(neededHandler);
问题是你最终得到一个对象的 IList,你需要将它们转换为正确的处理程序类型,这有点棘手......一个可能的解决方案是使用反射来调用 Handle()
方法:
var methodInfo = neededHandler.GetMethod("Handle");
object[] methodArgs = new object[] { eventToDispatch };
foreach (var h in handlers)
{
methodInfo.Invoke(h, methodArgs);
}
关于c# - 结构图 ObjectFactory.GetAllInstances<IHandle<TEvent>>(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6104058/