C# structuremap ObjectFactory.GetAllInstances<;IHandle<;TEvent>&燃气轮机;()

C# structuremap ObjectFactory.GetAllInstances<;IHandle<;TEvent>&燃气轮机;(),c#,structuremap,domain-events,C#,Structuremap,Domain Events,在最近的一个项目中,我在实施事件方面遇到了困难 我已经验证了structuremap正在正确地扫描、组装和添加EventHandler Scan(cfg => { cfg.TheCallingAssembly(); cfg.IncludeNamespace("ABC.EventHandler"); cfg.ConnectImplementationsToTypesClosi

在最近的一个项目中,我在实施事件方面遇到了困难

我已经验证了structuremap正在正确地扫描、组装和添加EventHandler

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);

            }

        }

    }
然后在我将域保存到存储库后引发它

 public static void Raise(ICollection<IDomainEvent> domainEvents)
        {
            foreach (var domainEvent in domainEvents)
            {
                DomainEventDispatcher.Raise(domainEvent);
            }

        }
公共静态无效提升(ICollection domainEvents)
{
foreach(域事件中的var domainEvent)
{
DomainEventDispatcher.Raise(domainEvent);
}
}
但是现在

ObjectFactory.GetAllInstances()
返回0个处理程序计数

如果我留意

ObjectFactory.GetAllInstances()
它正确地返回处理程序集合(目前我有2个,它显示2个计数)

。。。我假设这与作为
IDomainEvent
类型而不是实际类型引发的事件有关,这使得structuremap很难解决它

我如何解决这个问题

问候,

马尔

--

编辑1:

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

编辑2

我不知道如何使这个问题引起更多的注意。我正在为一个解决方案添加悬赏,以实现预期的结果。如果问题不清楚,请提问

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

我认为应该有某种方法让structuremap知道作为
IDomainEvent
引发的事件实际上是类型
DomainEvent

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

在dispatcher窗口中引发事件后

编辑3: 尽管eventToRaise显示为“DealerName已更改”和“DealerCommunications已更改”
typeof(TEvent)将类型指定为Domain.IDomainEvent

我猜想,如果有可能将其转换为正确的类型(VS watch window从中获取信息),那么问题可能会得到解决

-----结果---

这两种方法都奏效了。我把这两个问题都交给了我的团队中的另外两位成员,我们觉得这个没有经过思考的解决方案被选为正确答案

今天,我们将对已更改的实现进行测试,并查看解决方案中此解决方案是否存在任何问题

我对基于反射的解决方案投了赞成票,因为它也是正确的答案



正如您所说,问题是您正在为
IHandle
的所有实例请求structure map,而它没有这些实例,structuremap有具体事件的处理程序。您需要使用事件的实际类型构造类型,然后请求该事件的所有处理程序:

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

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

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
s的集合,而是保留一个
ieventrecord
的集合,该集合保存必要的类型数据以提升自身:

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

@仍在等待任何建议。
ObjectFactory.GetAllInstances()
是否返回您要查找的列表?否它返回没有处理程序的列表。如果执行
cfg.ConnectionImplementsToTypesClosing(typeof(IHandle))会发生什么
而不是在初始化过程中?@arootbeer-我将在几分钟内尝试向您更新我将在午餐后尽快应用此方法并更新结果。感谢您提供代码和解释。我将尝试实现这一点,并更新您刚刚有点困惑的“eventRecord.Raise(myDispatcher);”是否应该是eventRecord.Dispatcher(myDispatcher)?@TheMar-是的,应该是!更新了。@default.kramer-有了您答案中的信息,我可以让处理程序进入wor。我将尝试反射方法,只是为了比较它的效果。我会很快选择被接受的答案。。再次感谢你。
var record = CreateEventRecord(myDomainEvent);
foreach (var eventRecord in Records)
{
    eventRecord.Dispatch(myDispatcher);
}