2016-07-20 222 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

相關問題