回顧:NLayerAppV3是一個使用.net 2.1實作的經典DDD的分層架構的項目。
NLayerAppV3是在NLayerAppV2的基礎上,使用.net core2.1進行重新建構的;它包含了開發人員和架構師都可以重用的DDD層。
Github位址:https://github.com/cesarcastrocuba/nlayerappv3
上一篇,介紹了NLayerAppV3項目Infrastructure(基礎設施層)的Cross-Cutting部分,文章位址:https://www.cnblogs.com/net-yuan/p/NLayerAppV3-Infrastructure_CrossCutting.html
NLayerAppV3的基礎結構層一共分為兩個部分。處理資料相關的基礎元件Data和Cross-Cutting的基礎元件。
處理資料相關的基礎元件Data主要包含UOW和倉儲的實作;
Cross-Cutting的基礎元件目前主要包含資料擴充卡、國際化、驗證;
這篇本來應該介紹Infrastructure(基礎設施層)的Data部分。
可是倉儲的具體實作是放在基礎結構層的,而倉儲的接口則是放在領域模型層的。
是以,我們就先介紹領域層Domain。
NLayerAppV3項目的Domain(領域層)分為兩個部分:Seedwork和BoundedContext
Seedwork部分定義了實體的契約、實體的基類、值對象的基類、倉儲的契約、UOW的契約、規約等。
BoundedContext部分定義了聚合相關,聚合、值對象、規約的具體實作、倉儲的契約、領域服務等。
以下描述引用自何老大的博文:
聚合包裝一組高度相關的對象,作為一個資料修改的單元。
聚合最外層的對象稱為聚合根,它是一個實體。聚合根劃分出一個清晰的邊界,聚合根外部的對象,不能直接通路聚合根内部對象,如果需要通路内部對象,必須首先通路聚合根,再導航到聚合的内部對象。
聚合代表很強的包含關系,聚合内部的對象脫離了聚合,應該是毫無意義的,或不是你真正關注的,它是聚合的一個組成部分,這與UML中的組成聚合概念相近。
有關聚合的相關知識可以檢視何老大的博文 https://www.cnblogs.com/xiadao521/p/4141904.html
以BankAccount聚合來看,BankAccount是聚合根,包含卡号BankAccountNumber這樣的值對象,BankAccountNumber由國家或者地區銀行編号、檢查位等構成;Balance金額、Locked是否鎖定、Customer使用者實體、BankAccountActivity賬戶活動的集合等等、還包含鎖定、解鎖、存款等行為。這是一個充血的模型。
BankAccountFactory是建立聚合BankAccount的工廠,它負責建立BankAccount。
BankAccountSpecifications封裝了BankAccount的查詢規約
public static class BankAccountSpecifications
{
/// <summary>
/// Specification for bank accounts with number like to <paramref name="ibanNumber"/>
/// </summary>
/// <param name="ibanNumber">The bank account number</param>
/// <returns>Associated specification</returns>
public static ISpecification<BankAccount> BankAccountIbanNumber(string ibanNumber)
{
Specification<BankAccount> specification = new TrueSpecification<BankAccount>();
if (!String.IsNullOrWhiteSpace(ibanNumber))
{
specification &= new DirectSpecification<BankAccount>((b) => b.Iban
.ToLower()
.Contains(ibanNumber.ToLower()));
}
return specification;
}
}
View Code
IBankAccountRepository提供了BankAccount的倉儲契約
IBankTransferService提供了轉賬的領域服務契約,有一個轉賬方法
void PerformTransfer(decimal amount, BankAccount originAccount, BankAccount destinationAccount);
BankTransferService實作了IBankTransferService
實作了轉賬領域服務的邏輯。
public void PerformTransfer(decimal amount, BankAccount originAccount, BankAccount destinationAccount)
{
if (originAccount != null && destinationAccount != null)
{
var messages = LocalizationFactory.CreateLocalResources();
if (originAccount.BankAccountNumber == destinationAccount.BankAccountNumber) // if transfer in same bank account
throw new InvalidOperationException(messages.GetStringResource(LocalizationKeys.Domain.exception_CannotTransferMoneyWhenFromIsTheSameAsTo));
// Check if customer has required credit and if the BankAccount is not locked
if (originAccount.CanBeWithdrawed(amount))
{
//Domain Logic
//Process: Perform transfer operations to in-memory Domain-Model objects
// 1.- Charge money to origin acc
// 2.- Credit money to destination acc
//Charge money
originAccount.WithdrawMoney(amount, string.Format(messages.GetStringResource(LocalizationKeys.Domain.messages_TransactionFromMessage), destinationAccount.Id));
//Credit money
destinationAccount.DepositMoney(amount, string.Format(messages.GetStringResource(LocalizationKeys.Domain.messages_TransactionToMessage), originAccount.Id));
}
else
throw new InvalidOperationException(messages.GetStringResource(LocalizationKeys.Domain.exception_BankAccountCannotWithdraw));
}
}
View Code
參考: dax.net https://www.cnblogs.com/daxnet/archive/2011/06/07/2074451.html
何鎮汐 https://www.cnblogs.com/xiadao521/p/4141904.html