.NET Core开发实战(第26课:工程结构概览:定义应用分层及依赖关系)--学习笔记
26 | 工程结构概览:定义应用分层及依赖关系
从这一节开始进入微服务实战部分
这一节主要讲解工程的结构和应用的分层
在应用的分层这里定义了四个层次:
1、领域模型层
2、基础设施层
3、应用层
4、共享层
可以通过代码来看一下
共享层一共建立三个工程:
1、GeekTime.Core:主要承载基础的简单的类型,比如说异常或者一些帮助类
2、GeekTime.Domain.Abstractions:抽象层,领域的抽象是指在领域模型可以定义一些基类或者接口,领域事件接口,领域事件处理接口,还有 Entity 的接口和 Entity 的基类
3、GeekTime.Infrastructure.Core:基础设施的核心层,是指对仓储,还有 EFContext 定义一些共享代码

这些包实际上在不同的项目里面都可以共享,所以建议的做法是把这些代码都通过私有的 NuGet 的仓库来存储,然后其他的工程可以使用 NuGet 包来直接引用即可
领域模型层就是定义领域模型的地方,这里面会有不同的聚合,还有领域事件,不同的聚合下面就是领域模型

基础设施层是仓储层和一些共享代码的实现,这里只定义了仓储层的实现,包括 EF 的 DomainContext,还有 Order 的仓储层,User 的仓储层,还定义了领域模型与数据库之间的映射关系,就是在 EntityConfigurations 这目录下面去定义

应用层分两个,一个工程是 API 层,是用来承载 Web API 或者 Web 应用的,另外一个是后台任务,这个就是用来执行一些特殊的 Job,作为 Job 的宿主运行的,它可以是一个控制台的应用程序
在 Web 层,Web API 层,也分了几个关键目录 Application,Controllers,Extensions,Infrastructure
基础设施层会放一些身份认证缓存之类的与基础设施交互相关的一些代码
扩展层主要是将服务注册进容器的代码和中间件配置的代码,也就是两扩展方法,一个是对 ServiceCollection 的扩展,一个是对 ApplicationBuilder 的扩展
控制器层主要用来定义 Web API,这一层就是定义前后端交互的接口
应用层使用了 CQRS 的设计模式,就是命令与查询职责分离,把命令放在一个目录,把查询放在一个目录,同样的这里还有两个事件处理的目录,一个是领域模型,领域事件的处理,一个是集成事件的处理

再看一下各层之间的依赖关系
Shared 层实际上是不依赖任何层次的,它存储了共享的代码,被各个工程共享
GeekTime.Core,GeekTime.Domain.Abstractions 是不依赖任何工程的,而 GeekTime.Infrastructure.Core 依赖了 GeekTime.Domain.Abstractions,实现了仓储,比如说仓储会依赖 IAggregateRoot 接口
public interface IRepository<TEntity> where TEntity : Entity, IAggregateRoot

领域模型需要继承模型的基类,并且实现一个聚合根的接口,表示它是一个聚合根
public class Order : Entity<long>, IAggregateRoot
领域事件需要实现一个领域事件的接口
public class OrderCreatedDomainEvent : IDomainEvent

基础设施层是一个独立的程序集,实现了仓储的部分,定义了一个 Order 的仓储
public interface IOrderRepository : IRepository<Order, long>
还定义了 Order 仓储的实现
public class OrderRepository : Repository<Order, long, DomainContext>, IOrderRepository
{
public OrderRepository(DomainContext context) : base(context)
{
}
}
这里可以看到仓储实际上依赖了基础设施层共享代码里面的仓储的定义 IRepository,这样就可以复用仓储层的代码,这样定义 OrderRepository 就会比较简单,可以复用 Repository 的一些实现
public abstract class Repository<TEntity, TKey, TDbContext> : Repository<TEntity, TDbContext>, IRepository<TEntity, TKey> where TEntity : Entity<TKey>, IAggregateRoot where TDbContext : EFContext
{
public Repository(TDbContext context) : base(context)
{
}
public virtual bool Delete(TKey id)
{
var entity = DbContext.Find<TEntity>(id);
if (entity == null)
{
return false;
}
DbContext.Remove(entity);
return true;
}
public virtual async Task<bool> DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{
var entity = await DbContext.FindAsync<TEntity>(id, cancellationToken);
if (entity == null)
{
return false;
}
DbContext.Remove(entity);
return true;
}
public virtual TEntity Get(TKey id)
{
return DbContext.Find<TEntity>(id);
}
public virtual async Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{
return await DbContext.FindAsync<TEntity>(id, cancellationToken);
}
}
已经实现了一些基本的方法,增删改查的方法
数据库访问的实现,继承了自己定义的 EFContext,EFContext 作为共享代码在各个工程里面复用
public class DomainContext : EFContext
另外一个比较特殊的是事务处理的对象,这个对象是用来管理整个应用程序的请求上下文中的事务,这样就可以避免手动地去处理事务,简化代码
public class DomainContextTransactionBehavior<TRequest, TResponse> : TransactionBehavior<DomainContext, TRequest, TResponse>
{
public DomainContextTransactionBehavior(DomainContext dbContext, ICapPublisher capBus, ILogger<DomainContextTransactionBehavior<TRequest, TResponse>> logger) : base(dbContext, capBus, logger)
{
}
}

应用层依赖了基础设施层,基础设施层又依赖了领域层
应用层实际上是把各层组装在一起的这一层,它是应用程序的一个宿主,协调各层之间的关系,以及组装代码都是在这里实现的

总结一下
领域模型层专注于业务的设计,它不依赖于其他各层,它是相对独立的
基础设施的仓储层仅仅负责领域模型的存取,它不负责任何的业务逻辑代码的承载
推荐使用 CQRS 的模式来设计应用程序,使应用程序的代码结构更加的合理,在团队和项目膨胀的情况下,工程的可维护性不至于急剧的下降
Web API 是面向前端交互的接口,避免依赖领域模型
共享代码建议设计为共享包,使用私有的 NuGet 仓库来分发和管理
GitHub源码链接:
https://github.com/witskeeper/geektime



本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET Core开发实战(第26课:工程结构概览:定义应用分层及依赖关系)--学习笔记的更多相关文章
- 2月送书福利:ASP.NET Core开发实战
大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...
- [ASP.NET Core开发实战]开篇词
前言 本系列课程文章主要是学习官方文档,再输出自己学习心得,希望对你有所帮助. 课程大纲 本系列课程主要分为三个部分:基础篇.实战篇和部署篇. 希望通过本系列课程,能让大家初步掌握使用ASP.NET ...
- [ASP.NET Core开发实战]基础篇02 依赖注入
ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...
- .NET Core开发实战(第11课:文件配置提供程序)--学习笔记
11 | 文件配置提供程序:自由选择配置的格式 文件配置提供程序 Microsoft.Extensions.Configuration.Ini Microsoft.Extensions.Configu ...
- 2、SpringBoot接口Http协议开发实战8节课(1-6)
1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...
- [ASP.NET Core开发实战]基础篇03 中间件
什么是中间件 中间件是一种装配到应用管道,以处理请求和响应的组件.每个中间件: 选择是否将请求传递到管道中的下一个中间件. 可在管道中的下一个中间件前后执行. ASP.NET Core请求管道包含一系 ...
- [ASP.NET Core开发实战]基础篇01 Startup
Startup,顾名思义,就是启动类,用于配置ASP.NET Core应用的服务和请求管道. Startup有两个主要作用: 通过ConfigureServices方法配置应用的服务.服务是一个提供应 ...
- 2、SpringBoot接口Http协议开发实战8节课(7-8)
7.SpringBoot2.x文件上传实战 简介:讲解HTML页面文件上传和后端处理实战 1.讲解springboot文件上传 MultipartFile file,源自SpringMVC 1)静态页 ...
- [ASP.NET Core开发实战]基础篇06 配置
配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...
- [ASP.NET Core开发实战]基础篇05 服务器
什么是服务器 服务器指ASP.NET Core应用运行在操作系统上的载体,也叫Web服务器. Web服务器实现侦听HTTP请求,并以构建HttpContext的对象发送给ASP.NET Core应用. ...
随机推荐
- html5离线存储manifest
https://www.bilibili.com/video/BV1Up4y1t7pV?p=5
- 问题--VSCODE终端中文乱码问题
1.问题 问题如下,终端出现中文乱码问题 根本原因是VSCODE是UFT-8编码,而终端显示的中文则是GBK编码 网上很多都是改VSCODE为GBK编码,但改终端为UFT-8也挺方便 2.解决方法 1 ...
- C++模板显示指定类型时使用引用遇到的问题
1.问题 这里我想让模板函数接收int和char类型的参数,并进行相加,显示指定参数类型为int. 第一个调用理论上会自动将char类型强转成int类型,后进行相加: 第二个调用理论上会自动将int类 ...
- 【面试题精讲】MySQL中覆盖索引是什么
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 在MySQL中,覆盖索引是一种特殊类型的索引,它 ...
- [转帖]【终端使用】"usermod"命令 和 组(包括:主组、附加组)
"usermod"命令,可以用来设置用户账户的 主组.附加组.登录使用的Shell. 命令 作用 usermod -g 组名 用户名 修改用户的主组(gid) usermod ...
- 不同linux发行版 FIO测试结果总结
不同linux发行版 FIO测试结果总结 背景 机器来源 配置: 2路28核心Golden 6330 2.0Ghz 512G内存 硬盘 24块 960G SSD (22块 Raid5 + 2块 hot ...
- [转帖]Linux下使用 ipset 封大量IP及ipset参数说明
https://www.cnblogs.com/xiaofeng666/p/10952627.html Linux使用iptables封IP,是常用的应对网络攻击的方法,但要封禁成千上万个IP,如果添 ...
- [转帖]Linux命令拾遗-%iowait指标代表了什么?
https://www.cnblogs.com/codelogs/p/16060759.html 简介# 一直以来,我都知道top.vmstat.mpstat中有一个叫wa(%iowait)的cpu指 ...
- RN 动态渲染列表
写在组件中 想要图片出来还应该给图片宽高哈!! alignItems: 'center', //水平居中 动态渲染列表 返回的是一个数组 网络图片的渲染方式 <Image source={{ur ...
- sass中使用穿透属性(deep)修改第三方组件样似
<el-form-item> <el-button class="save-btn" type="primary" @click=" ...