structuremap ObjectFactory.GetAllInstances <ihandle <tevent>&gt;()</ihandle <tevent>

时间:2011-05-23 23:09:22

标签: c# structuremap domain-events

我正忙着在最近的一个项目中实现事件。

我已经验证了structmap正在正确扫描汇编和添加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类型而不是实际类型引发的事件有关,这使得structmap很难解决它。

我该如何解决这个问题?

此致

The Mar

-

编辑1:

我已经确定struturemap容器包含从程序集扫描的所有事件处理程序。

编辑2

我不知道如何让这个问题引起更多关注。我正在为获得所需结果的解决方案添加赏金。如果问题不明确,请询问。

基本上我希望 ObjectFactory.GetAllInstances<IHandle<TEvent>>() 返回TEvent TEvent类型为IDomainEvent的处理程序。要引发的事件存储在IDomainEvent的集合中,并在保存域(从服务层)之后引发。

我认为应该有一些方法可以让结构图知道引发为IDomainEvent的事件实际上是 DomainEvent

类型

var eventsToRaise = dealer.EventsToRaise(); 从调试窗口添加信息:

在调度程序窗口中引发事件后

enter image description here

编辑3: 尽管eventToRaise显示为“DealerName Changed”和“DealerCommunicationChanged” typeof(TEvent)将Type指定为Domain.IDomainEvent

我猜是否有可能能够投射到正确的类型(从VS观察窗口获取信息),问题可能得到解决

-----结果---

两种方法都有效。我把两个接近我的团队的其他两个成员,我们觉得没有反思的解决方案被选为正确答案。

今天我们将通过更改实施进行测试,看看解决方案中是否存在此解决方案的任何问题。

我推荐了基于反射的解决方案,因为它也是正确答案。


2 个答案:

答案 0 :(得分:4)

正如您所说,问题在于您要求IHandle<IDomainEvent>的所有实例的结构图,并且它没有这些实例,结构图具有针对具体事件的处理程序。您需要使用事件的实际类型构造类型,然后询问该事件的所有处理程序:

        Type genericHandler = typeof(IHandle<>);
        Type[] typeArgs = { eventToDispatch.GetType() };
        Type neededHandler = genericHandler.MakeGenericType(typeArgs);
        var handlers = ObjectFactory.GetAllInstances(neededHandler);

问题是你最终得到一个IList对象,你需要将它们转换为正确的处理程序类型,这有点棘手......一个可能的解决方案是使用反射来调用{{1}方法:

Handle()

答案 1 :(得分:1)

我建议使用记录来保存类型信息,而不是基于反射的方法。像这样:

interface IEventRecord
{
    void Dispatch(IEventDispatcher dispatcher);
}

public class EventRecord<TEvent> : IEventRecord where TEvent : IDomainEvent
{
    TEvent theEvent;

    public EventRecord(TEvent theEvent)
    {
        this.theEvent = theEvent;
    }

    public void Dispatch(IEventDispatcher dispatcher)
    {
        dispatcher.Dispatch(theEvent);
    }
}

如果您发现实例化事件记录很麻烦,帮助程序可以推断出类型参数,如下所示:

public static EventRecord<TEvent> CreateEventRecord<TEvent>(TEvent theEvent) where TEvent : IDomainEvent
{
    return new EventRecord<TEvent>(theEvent);
}

这将允许您实例化事件记录,如下所示:

var record = CreateEventRecord(myDomainEvent);

然后,不要抓住IDomainEvent的集合,而是抓住一个IEventRecords的集合,其中包含必要的类型数据以提升自己:

foreach (var eventRecord in Records)
{
    eventRecord.Dispatch(myDispatcher);
}