NLayerAppV3--.net Core2实现的DDD分层架构

        虽然每天的工作都是CURD、还是使用着传统的三层架构、使用着.net Framework,但是这并不能影响我学习DDD和.net core。

总是希望软件在应对复杂多变的场景时能够游刃有余,在解决问题时能够多一种选择。

        很早就有关注大神dax.net的NLayerApp系列博文https://www.cnblogs.com/daxnet/category/304141.html

        近期入坑.net core,看了进击的辣条的文章Asp.Net Core微服务初体验,很有收获,感谢感谢。

        抽时间读了下NLayerAppV3项目的源码,Github地址:https://github.com/cesarcastrocuba/nlayerappv3

分享下体会,希望相互交流学习,谢谢!

1、项目简介

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

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

2、项目结构

放一张DDD风格架构l图。主要分为四层:表现层、应用层、领域层和基础结构层。

详细的各层的含义可以查看dax.net的文章https://www.cnblogs.com/daxnet/archive/2011/05/10/2042095.html

1.1-Presentation(表现层)

系统和用户的交互层。UI展示给终端用户、收集用户的反馈信息。

1.2-Distributed Services(分布式服务层)

为应用程序提供远程访问;如果是http协议,一般设计为WebApi。

1.2.1-Seedwork --DistributedServices.Seedwork

分布式服务的Controller、Filter等

1.2.2-MainBoundedContext

--DistributedServices.MainBoundedContext

以银行的业务示例,构建上下文、对外提供WebApi服务,结合Swagger UI

--DistributedServices.MainBoundedContext.Tests

DistributedServices.MainBoundedContext的测试项目

1.2.3-BlogContext

--DistributedServices.BlogBoundedContext

以博客业务示例,构建上下文,对外提供WebApi服务,结合Swagger UI

--DistributedServices.BlogBoundedContext.Tests

DistributedServices.BlogBoundedContext项目的测试项目

1.3-Application(应用层)

协调领域模型与其它应用、包括事务调度、UOW、数据转换等。

主要作用:通过仓储来访问持久层;对不同领域的数据组织整理;协调领域对象之间、领域对象与基础层的协作关系;应用服务等

1.3.1-Seedwork --Application.Seedwork

应用层共用接口、实现的封装

1.3.2-MainBoundedContext

--Application.MainBoundedContext

业务模块的应用层服务接口和实现

--Application.MainBoundedContext.DTO

应用层业务模块的数据转换等

--Application.MainBoundedContext.Tests

Application.MainBoundedContext的测试项目

1.3.3-BlogBoundedContext

同1.3.2,不同的是业务换为博客业务

1.4-Domain(领域层)

展现业务/领域逻辑、业务处理状态,以及实现业务规则,它同时也包含了领域对象的状态信息。

1.4.1-Seedwork

--Domain.Seedwork

领域层实体基类、仓储接口、UOW接口、值对象基类、规约等

--Domain.Seedwork.Tests

Domain.Seedwork的测试项目

1.4.2-MainBoundedContext

--Domain.MainBoundedContext

实体、值对象、领域服务、聚合根、聚合及工厂

--Domain.MainBoundedContext.Tests

Domain.MainBoundedContext的测试项目

1.4.3-BlogBoundedContext

同1.4.2 业务逻辑换成了博客

1.5-Infrastructure(基础设施层)

1.5.1-Data  

为应用程序的数据存取提供服务,它可以是应用程序本身的持久化机制,也可以是外部系统提供的数据访问的Web Service等

--Infrastructure.Data.Seedwork

UOW的实现基类、仓储的实现基类

--Infrastructure.Data.MainBoundedContext

UOW的实现、仓储的实现

--Infrastructure.Data.MainBoundedContext.Tests

Infrastructure.Data.MainBoundedContext的测试项目

1.5.2-CrossCutting 

该层提供了能被其它各层访问的通用技术框架,比如异常捕获与处理、日志、认证、授权、验证、跟踪、监视、缓存等等。

--Infrastructure.Crosscutting

适配器、国际化、验证等接口的封装

--Infrastructure.Crosscutting.NetFramework

适配器、国际化、验证等实现、国际化依赖的资源

--Infrastructure.Crosscutting.Tests

Infrastructure.Crosscutting的测试项目

3、示例

以DistributedServices.MainBoundedContext项目的BankAccounts的转账api示例,说明下我的理解

[HttpPut]public void PerformTransfer([FromBody]BankAccountDTO from, [FromBody]BankAccountDTO to, [FromBody]decimal amount){_bankAppService.PerformBankTransfer(from, to, amount);}
View Code

_bankAppService通过构造函数注入。

readonly IBankAppService _bankAppService;public BankAccounts(IBankAppService bankAppService){_bankAppService = bankAppService;}
View Code

IBankAppService是应用层的服务接口

对应的应用层有接口的实现BankAppService

public BankAppService(IBankAccountRepository bankAccountRepository, // the bank account repository dependencyICustomerRepository customerRepository, // the customer repository dependency
                              IBankTransferService transferService,ILogger<BankAppService> logger){//check preconditionsif (bankAccountRepository == null)throw new ArgumentNullException("bankAccountRepository");if (customerRepository == null)throw new ArgumentNullException("customerRepository");if (transferService == null)throw new ArgumentNullException("trasferService");_bankAccountRepository = bankAccountRepository;_customerRepository = customerRepository;_transferService = transferService;_logger = logger;_resources = LocalizationFactory.CreateLocalResources();}
View Code

BankAppService通过构造函数注入了领域层的银行账号仓储IBankAccountRepository和客户仓储ICustomerRepository、转账服务等,全部依赖于接口。

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 transactionif (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

实现转账的功能,输入参数都是Dto对象,通过AutoMapper或者其它映射工具完成数据转换;通过仓储访问聚合,获取源和目标账号信息、开启事务,UOW提交转账操作。

DistributedServices.MainBoundedContext的StartUp中注册IOC

仓储、领域服务、应用层服务、适配器、国际化、验证、Swagger UI等。

运行项目

在DistributedServices.MainBoundedContext目录下打开cmd命令,输入dotnet restore,完成之后,输入dotnet run

运行结果:

 4、想法和计划

跟.net core microservice结合

使用ocelot搭建服务网关、结合identityserver4实现授权认证;polly服务熔断;限流;consul服务发现;Appolo配置中心;Skywalking追踪结果。

转载于:https://www.cnblogs.com/net-yuan/p/NLayerAppV3.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/425512.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java学习笔记11-1——Spring5

文章目录1.简介组成拓展2.控制反转&#xff08;IoC&#xff09;IoC例子IoC本质3.Hello&#xff0c;Springdemo1修改user例子的代码思考4.IoC创建对象的方式通过无参构造的方式通过有参构造的方式5.Spring配置alias 设置别名Bean的配置import6.依赖注入&#xff08;DI&#xff0…

空间滤波增强

基本概念 空间域滤波增强采用模板处理方法对图像进行 滤波&#xff0c;去除图像噪声或增强图像的细节 空间域平滑滤波器 分析&#xff1a;任何一幅原始图像&#xff0c;在其获取和传输等过程中&#xff0c; 会受到各种噪声的干扰&#xff0c;使图像模糊&#xff0c;对图像分析…

[剑指offer][JAVA]面试题第[27]题[二叉树的镜像][递归][栈]

【问题描述】[中等] 请完成一个函数&#xff0c;输入一个二叉树&#xff0c;该函数输出它的镜像。例如输入&#xff1a;4/ \2 7/ \ / \ 1 3 6 9 镜像输出&#xff1a;4/ \7 2/ \ / \ 9 6 3 1示例 1&#xff1a;输入&#xff1a;root [4,2,7,1,3,6,9]…

瓶颈分析

Top指令&#xff1a; CPU/内存情况 top # top指令可以显示总体CPU占用率、内存使用率和交换情况&#xff0c;以及所有进程对应的CPU、内存占用情况 终端下使用该指令示例结果&#xff1a; 上图对一些重要的参数进行了简单标识&#xff0c;笔者这里使用的是XShell对远程Linux服务…

Java学习笔记11-2——Spring5

文章目录7.Bean的自动装配自动装配说明测试环境搭建byName&#xff08;按名称自动装配&#xff09;测试byName运行机制小结&#xff1a;byType&#xff08;按类型自动装配&#xff09;测试使用注解进行自动装配AutowiredQualifierResourceAutowired与Resource异同8.使用注解开发…

频率域平滑滤波器

频率域滤波增强方法 理想低通滤波器 理想低通滤波器(Ideal Lowpass Filters-ILPF) 尽管理想低通滤波器在数学上定义清楚&#xff0c;在计算机模拟中也可 实现&#xff0c;但在截止频率处直上直下的理想低通滤波器是不能用实际的 电子器件实现的。 理想滤波器有陡峭频率的截止…

[leetcode][JAVA]面试题第[1028]题[迭代]

【问题描述】[困难] 我们从二叉树的根节点 root 开始进行深度优先搜索。 在遍历中的每个节点处&#xff0c;我们输出 D 条短划线&#xff08;其中 D 是该节点的深度&#xff09;&#xff0c;然后输出该节点的值。&#xff08;如果节点的深度为 D&#xff0c;则其直接子节点的…

频率域锐化滤波器

频率域锐化滤波器 &#xff08;Frequency Sharpening Filters &#xff09; 图像的边缘、细节主要位于高频部分&#xff0c;而图 像的模糊是由于高频成分比较弱产生的。 频率域锐化就是为了消除模糊&#xff0c;突出边缘。 采用高通滤波器让高频成分通过&#xff0c;使低频成 …

6用NetBeans进行JSP开发

用NetBeans进行JSP开发 NetBeans

Java学习笔记12——JVM入门

文章目录JVM简介和体系结构JVM的位置JVM的体系结构类加载器双亲委派机制沙箱安全机制&#xff08;了解即可&#xff09;NativePC寄存器方法区栈三种JVM堆新生区永久区堆内存调优Jprofiler的使用GC&#xff08;垃圾回收&#xff09;引用计数法复制算法标记清除法标记压缩法GC算法…

[Leedcode][JAVA][第125题][验证回文串][双指针][String]

【问题描述】[简单] 给定一个字符串&#xff0c;验证它是否是回文串&#xff0c;只考虑字母和数字字符&#xff0c;可以忽略字母的大小写。说明&#xff1a;本题中&#xff0c;我们将空字符串定义为有效的回文串。示例 1:输入: "A man, a plan, a canal: Panama" 输…

面向对象之:继承

一&#xff1a;什么面向对象的继承&#xff1f; 比较官方的说法就是&#xff1a; 继承&#xff08;英语&#xff1a;inheritance&#xff09;是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B&#xff0c;就把这个A称为“B的子类别”&#xff0c;而…

7用Eclipse进行JSP开发

用Eclipse进行JSP开发 Eclipse简介和下载 Eclipse的发展 什么是Eclipse Eclipse下载 用Eclipse进行JSP开发 软件环境配置 安装JDK&#xff0c;配置Java运行环境 安装Tomcat服务器&#xff08;服务器能够正常启动和关闭&#xff09; 安装Eclipse JSP开发

求递归算法时间复杂度:递归树

引用自&#xff1a;http://www.cnblogs.com/wu8685/archive/2010/12/21/1912347.html 递归算法时间复杂度的计算方程式一个递归方程&#xff1a; 在引入递归树之前可以考虑一个例子&#xff1a; T(n) 2T(n/2) n2 迭代2次可以得&#xff1a; T(n) n2 2(2T(n/4) (n/2) 2) 还…

[Leetcode][JAVA]第[29]题[两数相除][二分法]

【问题描述】[中等] 给定两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求不使用乘法、除法和 mod 运算符。返回被除数 dividend 除以除数 divisor 得到的商。整数除法的结果应当截去&#xff08;truncate&#xff09;其小数部分&#xff0c;…

8.用MyEclipse进行JSP开发

用MyEclipse进行JSP开发

Java学习笔记13-1——SpringMVC

文章目录1.什么是MVC回顾Servlet2.什么是SpringMVC概述中心控制器SpringMVC执行原理3.第一个SpringMVC 程序使用XML配置实现使用注解实现4.控制器和RestFul风格控制器Controller实现Controller接口使用注解ControllerRequestMappingRestFul 风格扩展&#xff1a;小黄鸭调试法5.…

端口占用怎么查找

D:\Users\hp\Documents\NetBeansProjects\WebApplication1\nbproject\build-impl.xml:1030: Deployment error: Starting of Tomcat failed, the server port 8080 is already in use. netstat -aon|findstr "8080" 查看端口 查看端口的进程 记住3306 tasklist|fi…

eclipse没有server怎么办

1打开eclipse 找到help 2点开&#xff0c;查找 Install new software 二步、然后在Work with中点击Add&#xff0c;如下图所示&#xff0c;加入Name"Kepler" repository&#xff1b;Locationhttp://download.eclipse.org/releases/kepler。 3填写完成后使用add 4第…

zabbix利用SNMPTrap接收交换机主动告警

zabbix接收trap的工作流程&#xff1a; snmptrapd 收到trapsnmptrapd将trap传递给SNMPTT或调用Perl接收器SNMPTT或Perl trap接收器解析&#xff0c;格式化并将trap写入文件Zabbix SNMP trap读取并解析trap文件对于每个trap&#xff0c;Zabbix发现主机接口与接收的trap地址匹配的…