NLayerAppV3-Distributed Service Layer(分布式服务层)

回顾:NLayerAppV3是一个使用.net 2.1实现的经典DDD的分层架构的项目。

NLayerAppV3是在NLayerAppV2的基础上,使用.net core2.1进行重新构建的;它包含了开发人员和架构师都可以重用的DDD层。

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

本篇介绍Distributed Service Layer(分布式服务层)

1、Distributed Service Layer(分布式服务层)

借用dax.net的话:
当应用程序以服务提供商(Service Provider)的方式向其它远程应用程序提供业务功能时,或者应用程序的客户端本身是被部署在另一个远程位置时,其业务逻辑就必须通过分布式服务层向外界发布。
分布式服务层(通常被实现为Web Service)可以根据可配置的通信通道与数据消息格式,为应用程序提供远程访问的功能。需要注意的是,分布式服务层中不应该包含任何业务逻辑的实现。

DistributedServices.MainBoundedContext项目,创建的是.net core2.1 webapi项目。
RESTful方式
BankAccounts通过构造函数注入应用层的IBankAppService契约,调用应用层的业务,对外提供服务;Startup类中配置EntityFramework、各种依赖注入、swagger UI的相关配置

.net core2中如何使用swagger,网上有好多介绍,也可以查看其GitHub:https://github.com/domaindrivendev/Swashbuckle.AspNetCore
为了应对服务的版本变化,使用swagger可以实现api服务多版本控制,可以参考这篇文章https://www.cnblogs.com/intotf/p/10075331.html

进阶:有了api服务,那么api服务的认证和授权问题,如何解决呢?,可以使用identityserver4;如果只需要认证,则结合jwt,就可以实现。

2、总结 

NLayerAppV3的基础设施层、领域层、应用层、分布式服务层到目前就基本介绍完了,我们来总结下

基础设施层

包含了两个部分:Data部分和CrossCutting部分;

Data部分是仓储的层超类型、UOW以及仓储的实现。
CrossCutting部分则提供了通用功能的支撑,目前包含三部分:适配器、国际化和验证。分两个项目,一个项目是定义契约,另一个是实现。
领域层,是核心部分
包含仓储的契约、实体的接口和基类、值对象的基类、UOW契约、规约等;聚合的划分、领域服务等。
应用层
协调领域模型与其它应用、包含事务调度、UOW、事务等。
分布式服务层
调用应用层对外提供服务。

3、调用关系

我们以银行转账业务为例,说明各层的调用逻辑关系
服务http://localhost:55638/api/BankAccounts PUT
输入源账户信息、目标账户信息、转账金额,服务接收到的是对应的DTO对象;
然后调用应用层的转账方法,应用层接收参数,利用仓储调用查找有无对应的账户实体,如果有,则开始转账:
开启事务,调用领域层的转账服务转账,仓储调用UOW,提交,事务完成,关闭事务。

银行转账的应用层服务代码

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

 

posted @ 2019-03-08 11:15  net-yuan  阅读(697)  评论(0编辑  收藏  举报