2016-07-20 139 views
3

我试图使用CQRS & DDD购买域名模式,我知道,我提出在域中的事件,但我不知道在哪里,当我使用命令来注册。事件处理程序是否应该在命令处理程序中注册?或者我误解了一些东西。这是我的过程,你能帮助建模吗?注册事件处理程序在CQRS

完成采购订单命令被给出,比命令处理程序终止订单(从存储库获取订单,更改其状态并保存回数据库),订单终止事件发生在域模型中,比事件处理程序使用标识符订单项,找到供应商的联系信息(可能是电子邮件,甚至外部服务),并通知他有关新的采购订单。

我的命令&命令处理程序是在应用层(事件处理程序也应该在这里?)。 域模型,事件和域图层中的IRepositories。 基础架构层中的存储库实现。

域模型(跳过大多数属性):

public class PurchaseOrder 
{ 
    public PurchaseOrder(int purchaseOrderID, int supplierID, bool isOrderFinalized) 
    { 
     PurchaseOrderID = purchaseOrderID; 
     SupplierID = supplierID; 
     IsOrderFinalized = isOrderFinalized; 
    } 
    public int PurchaseOrderID { get; private set; } 
    public int SupplierID { get; private set; } 
    public bool IsOrderFinalized { get; private set; } 

    public static PurchaseOrder CreateNew(int supplierID) 
    { 
     return new PurchaseOrder(0, supplierID, false); 
    } 

    public void FinalizeOrder() 
    { 
     IsOrderFinalized = true; 
     DomainEvents.Raise(new PurchaseOrderFinalized(PurchaseOrderID)); 
    } 
} 

FinalizePurchaseOrder命令

public class FinalizePurchaseOrder : ICommand 
{ 
    public FinalizePurchaseOrder (int purchaseOrderID) 
    { 
     PurchaseOrderID = purchaseOrderID; 
    } 
    public int PurchaseOrderID { get; private set; } 
} 

命令处理程序

public class PurchaseOrdersCommandHandler : ICommandHandler<FinalizePurchaseOrder> 
{ 
    public void Handle(FinalizePurchaseOrder command) 
    { 
     var purchaseOrder = purchaseOrderRepository.FindByID(command.PurchaseOrderID); 
     // Should i register event handler here? 
     // DomainEvents.Register<PurchaseOrderFinalized>(PurchaseOrderFinalizedHandler); 
     purchaseOrder.FinalizePurchaseOrder(); 
     purchaseOrderRepository.Save(purchaseOrder); 
    } 
} 

事件和事件处理程序是这样的:

public class PurchaseOrderFinalized 
{ 
    public PurchaseOrderFinalized(int purchaserOrderID) 
    { 
     PurchaseOrderID = purchaseOrderID; 
    } 
} 

public void PurchaseOrderFinalizedHandler (PurchaseOrderFinalized evt) 
{ 
    // TODO: Get PurchaseOrder with its line items, and notify supplier about new order 
} 

回答

3

是否应的事件处理程序命令处理程序进行注册?

不除非它们是动态的,没有。您通常会将它们连接到您的应用程序的CompositionRoot。这个想法是,所有的接线都是在你的应用程序加载完成之前和“准备就绪”之前进行的。

你在哪里注册你的命令处理程序?你应该在同一个地方注册你的事件处理程序。

[更新]

举一个例子,看https://github.com/gregoryyoung/m-r/blob/master/CQRSGui/Global.asax.cs

+0

我没有注册的命令处理程序还没有,我只是有域和应用层,我使用了一些测试,单元测试。我读过有关CompositionRoot,所以我在MVC我会在Global.asax中注册指挥事件处理程序的情况下得到了它,我已经看到了例如人们使用NServiceBus注册和发送命令/事件,我是正确,这也是DI容器? – QuietNaN

+0

NServiceBus不是DI容器,而是服务总线。如果你是刚刚开始,我不会用一个DI容器可言,只能把它当纯DI成为一个问题,否则仅仅是另一回事学习 – tomliversidge

+0

明白了,你能不能给我一些链接,我可以拿对其中的命令/事件处理程序被注册代码示例来看看(不使用nservicebus)在CompositionRoot以及他们如何在应用程序中使用。建议使用服务总线吗? – QuietNaN

0

您应该查看乌迪大汉的演讲上Reliable Messaging.

典型架构通常包括消息队列/事件总线的一番风味。您的事件处理程序在启动时将其预订注册到总线事件中。正如@tomliversidge指出的那样,通常会在组合根部。

当您将更改保存到您的集合体,还可以节省已通过命令提出的DomainEvents。这两种写法发生在相同的交易中,在相同的记录册中。所以他们都成功了,或者都失败了。

如果交易失败,那么数据模型并没有改变,也没有人需要通知的任何东西 - 故障报告给客户端和平日一样,你的生活。

如果命令成功,那么我们需要安排要发布的事件。这是一个基本的异步操作 - 任何其他由事件处理程序写入记录簿的操作都将处于其自己的事务中。

自然的事情是让你的命令处理程序安排的事件发布到总线的任务。计划了任务后,命令处理程序返回(它并不关心任务何时运行)。

但由于事件是在书中记录的,可以再次发布他们在喜欢的时候。

+0

谢谢您的回答,我将回顾从家里演示,VIMEO被阻断我的工作场所。 – QuietNaN

相关问题