天天看點

NLayerAppV3-Infrastructure(基礎結構層)的Data部分和Application(應用層)

回顧:NLayerAppV3是一個使用.net 2.1實作的經典DDD的分層架構的項目。

NLayerAppV3是在NLayerAppV2的基礎上,使用.net core2.1進行重新建構的;它包含了開發人員和架構師都可以重用的DDD層。

Github位址:https://github.com/cesarcastrocuba/nlayerappv3

NLayerAppV3的基礎結構層一共分為兩個部分。處理資料相關的基礎元件和Cross-Cutting的基礎元件。

處理資料相關的基礎元件主要包含UOW和倉儲的實作;

Cross-Cutting的基礎元件目前主要包含資料擴充卡、國際化、驗證;

本篇介紹NLayerAppV3的Infrastructure(基礎結構層)的Data部分和Application(應用層)

1、Infrastructure(基礎結構層)的Data部分

Data部分是處理資料相關的基礎元件主要包含UOW和倉儲的實作。

UOW的實作:BaseContext繼承了DbContext和IQueryableUnitOfWork

DbContext是EF Core資料庫上下文,包Microsoft.EntityFrameworkCore

IQueryableUnitOfWork繼承IUnitOfWork和ISql,是EF Core方式的契約定義

Isql定義了支援sql語句的方式

Repository倉儲的層超類型,通過構造函數注入了IQueryableUnitOfWork和ILogger,定義了EF Core方式的CURD以及查詢過濾,包括分頁等行為

MainBCUnitOfWork實作了BaseContext。示例使用記憶體資料庫的方式來示範,當然,根據實際需要,可以很容易地擴充使用sqlserver、mysql、sqlite等,這也符合了開閉原則

BankAccountRepository是BankAccount倉儲,繼承Repository<BankAccount>,IBankAccountRepository,通過構造函數注入了MainBCUnitOfWork和ILogger,提供了一個GetAll方法,用來擷取BankAccount的集合。

NLayerAppV3-Infrastructure(基礎結構層)的Data部分和Application(應用層)
NLayerAppV3-Infrastructure(基礎結構層)的Data部分和Application(應用層)
public class BankAccountRepository
        :Repository<BankAccount>,IBankAccountRepository
    {
        #region Constructor

        /// <summary>
        /// Create a new instance
        /// </summary>
        /// <param name="unitOfWork">Associated unit of work</param>
        /// <param name="logger">Logger</param>
        public BankAccountRepository(MainBCUnitOfWork unitOfWork,
            ILogger<Repository<BankAccount>> logger)
            : base(unitOfWork, logger)
        {
            
        }

        #endregion

        #region Overrides

        /// <summary>
        /// Get all bank accounts and the customer information
        /// </summary>
        /// <returns>Enumerable collection of bank accounts</returns>
        public override IEnumerable<BankAccount> GetAll()
        {
            var currentUnitOfWork = this.UnitOfWork as MainBCUnitOfWork;

            var set = currentUnitOfWork.CreateSet<BankAccount>();

            return set.Include(ba => ba.Customer)
                      .AsEnumerable();
            
        }
        #endregion
    }      

View Code

2、Application(應用層)

協調領域模型與其它應用、包括事務排程、UOW、資料轉換等。

IService定義了應用層服務的契約。Service實作了IService,通過構造函數注入IRepository,為什麼要注入IRepository?

因為要擷取實體的相關資訊,就必須通過倉儲去操作聚合,而聚合是通過聚合根跟外部聯系的。

ProjectionsExtensionMethods作用是使用擴充方法,将實體轉換為DTO或者将實體集合轉換為DTO的集合

IBankAppService定義了Bank的應用層契約。有開戶、查找賬戶、鎖定賬戶、查找賬戶活動集、轉賬等業務。

BankAppService實作了IBankAppService。通過構造函數注入IBankAccountRepository、ICustomerRepository、IBankTransferService、ILogger。

IBankAccountRepository是BankAccount的倉儲契約;

ICustomerRepository是Customer使用者的倉儲契約;

IBankTransferService是轉賬的領域服務;

轉賬方法的代碼:

NLayerAppV3-Infrastructure(基礎結構層)的Data部分和Application(應用層)
NLayerAppV3-Infrastructure(基礎結構層)的Data部分和Application(應用層)
public void PerformBankTransfer(BankAccountDTO fromAccount, BankAccountDTO toAccount, decimal amount)
        {
            //Application-Logic Process: 
            // 1º Get Accounts objects from Repositories
            // 2º Start Transaction
            // 3º Call PerformTransfer method in Domain Service
            // 4º If no exceptions, commit the unit of work and complete transaction

            if (BankAccountHasIdentity(fromAccount)
                &&
                BankAccountHasIdentity(toAccount))
            {
                var source = _bankAccountRepository.Get(fromAccount.Id);
                var target = _bankAccountRepository.Get(toAccount.Id);

                if (source != null & target != null) // if all accounts exist
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        //perform transfer
                        _transferService.PerformTransfer(amount, source, target);

                        //comit unit of work
                        _bankAccountRepository.UnitOfWork.Commit();

                        //complete transaction
                        scope.Complete();
                    }
                }
                else
                    _logger.LogError(_resources.GetStringResource(LocalizationKeys.Application.error_CannotPerformTransferInvalidAccounts));
            }
            else
                _logger.LogError(_resources.GetStringResource(LocalizationKeys.Application.error_CannotPerformTransferInvalidAccounts));

        }      

View Code

Application.MainBoundedContext.DTO項目

項目中是所有的DTO對象和使用AutoMapper轉換的配置轉換規則的Profile檔案。

這裡的Profile檔案是在Infrastructure(基礎設施層)Crosscutting部分的Adapter(擴充卡)中AutomapperTypeAdapterFactory(AutoMapper的類型轉換器建立工廠)建立AutomapperTypeAdapter(AutoMapper的類型轉換器)時使用反射的方式調用的。