实现领域驱动设计 - 使用ABP框架 - 领域服务
领域服务
领域服务实现领域逻辑
- 依赖于服务和存储库。
- 需要处理多个聚合,因为该逻辑不适合任何聚合。
领域服务与领域对象一起工作。它们的方法可以获取并返回实体、值对象、原始类型……但是,它们不获取/返回dto。dto是应用层的一部分
示例:分配问题给用户
记住问题分配是如何在问题实体中实现的
public class Issue : AggregateRoot<Guid>
{
public Guid? AssignedUserId { get; private set; }
public async Task AssignToAsync(AppUser user, IUserIssueService userIssueService)
{
var openIssueCount = await userIssueService.GetOpenIssueCountAsync(user.Id);
if(openIssueCount >= 3)
{
throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");
}
AssignedUserId = user.Id;
}
public void CleanAssignment()
{
AssignedUserId = null;
}
}
在这里,我们将把这个逻辑转移到领域服务中。
首先,修改Issue类:
public class Issue : AggregateRoot<Guid>
{
public Guid? AssignedUserId { get; internal set; }
}
- 删除了与分配问题相关的方法。
- 将 AssignedUserId 属性的setter从私有改为内部,以允许从领域服务设置它
下一步是创建一个名为 IssueManager 的领域服务,该服务具有AssignToAsync 来将给定问题分配给给定用户
public class IssueManager : DomainService
{
private readonly IRepository<Issue, Guid> _issueReposiroty;
public IssueManager(IRepository<Issue, Guid> issueReposiroty)
{
_issueReposiroty = issueReposiroty;
}
public async Task AssignToAsync(Issue issue, AppUser user)
{
var openIssueCount = await _issueRepository.CountAsync(i => i.AssignedUserId == user.Id && !i.IsClosed);
if(openIssueCount >= 3)
{
throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");
}
issue.AssignedUserId = user.Id;
}
}
IssueManager 可以注入任何依赖的服务,并用于查询用户的分配问题数量。
我们更喜欢并建议为领域服务使用 Manager 后缀。
这个设计的唯一问题就是 Issue.AssignedUserId 现在在类外开放设置了。然而,它不是公开的。它是内部的,并且只能在同一个程序集中(IssueTracking)进行更改。此示例解决方案的领域项目。我们认为这是合理的
- 领域层开发人员已经知道领域规则,他们使用 IssueManager
- 应用层开发人员已经被强制使用IssueManager,他们不直接设置它。
虽然两种方法之间存在权衡,但当业务逻辑需要使用外部服务时,我们更喜欢创建域服务
如果你没有一个好的理由,我们认为没有必要为领域服务创建接口(比如为IssueManager创建IIssueManager)
实现领域驱动设计 - 使用ABP框架 - 领域服务的更多相关文章
- 实现领域驱动设计 - 使用ABP框架 - 什么是领域驱动设计?
前言: 最近看到ABP官网的一本电子书,感觉写的很好,翻译出来,一起学习下 (Implementing Domain Driven Design) https://abp.io/books DDD简介 ...
- 实现领域驱动设计 - 使用ABP框架 - 通用准则
在进入细节之前,让我们看看一些总体的 DDD 原则 数据库提供者 / ORM 无关性 领域和应用程序层应该与 ORM / 数据库提供程序 无关.它们应该只依赖于 Repository 接口,而 Rep ...
- 实现领域驱动设计 - 使用ABP框架 - 解决方案概览
.NET解决方案的分层 下图显示了使用ABP的 应用启动模板 创建的Visual Studio解决方案: 解决方案名称为问题跟踪,它由多个项目组成.通过考虑DDD原则以及开发和部署实践,该解决方案是分 ...
- 实现领域驱动设计 - 使用ABP框架 - 存储库
存储库 Repository 是一个类似于集合的接口,领域层和应用程序层使用它来访问数据持久性系统(数据库),以读写业务对象(通常是聚合) 常见的存储库原则是: 在领域层定义一个存储库接口(因为它被用 ...
- 实现领域驱动设计 - 使用ABP框架 - 创建实体
用例演示 - 创建实体 本节将演示一些示例用例并讨论可选场景. 创建实体 从实体/聚合根类创建对象是实体生命周期的第一步.聚合/聚合根规则和最佳实践部分建议为Entity类创建一个主构造函数,以保证创 ...
- 基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑
目录 系列文章 领域逻辑和应用逻辑 多应用层 示例:正确区分应用逻辑和领域逻辑 学习帮助 系列文章 基于ABP落地领域驱动设计-00.目录和前言 基于ABP落地领域驱动设计-01.全景图 基于ABP落 ...
- 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇
前言 领域驱动设计,其实已经是一个很古老的概念了,但它的复杂度依旧让学习的人头疼不已. 互联网关于领域驱动的文章有很多,每一篇写的都很好,理解领域驱动设计的人都看的懂. 不过,这些文章对于那些初学者而 ...
- .net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇
.net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以. ...
- 基于ABP落地领域驱动设计-00.目录和小结
<实现领域驱动设计> -- 基于 ABP Framework 实现领域驱动设计实用指南 翻译缘由 自 ABP vNext 1.0 开始学习和使用该框架,被其优雅的设计和实现吸引,适逢 AB ...
- 基于ABP落地领域驱动设计-05.实体创建和更新最佳实践
目录 系列文章 数据传输对象 输入DTO最佳实践 不要在输入DTO中定义不使用的属性 不要重用输入DTO 输入DTO中验证逻辑 输出DTO最佳实践 对象映射 学习帮助 系列文章 基于ABP落地领域驱动 ...
随机推荐
- nvim及插件安装配置
1. install neovim 1 sudo apt install neovim After installing neovim, we can delete old vi. 3. instal ...
- MongoDB:【索引的管理操作】
- sql注入学校后台
有运气成分,遇到两个学校,子域名查询了一下发现有登录平台,然后就直接sql了 payload:admin'or 1=1--+ 很离谱,这年头这两学校还能直接被sql进入后台. 然后进学校后台后就可以直 ...
- C#中DevExpress的GridControl相关表格的属性总结
这里用到了Dev中的GridControl表格做数据查询展示,要求字号大一些,单行选中深色显示 // grid1 this.grid1.Dock = System.Windows.Forms.Dock ...
- 使用twinkle-tray快捷调整多个显示器的亮度
前言 自从安装了这个小工具,我再也没用过笔记本键盘上的快捷键了~ 介绍 Twinkle Tray enables brightness control on external displays in ...
- Luogu P2414 NOI2011 阿狸的打字机 题解 [ 紫 ] [ AC 自动机 ] [ 离线思想 ] [ 树状数组 ] [ dfs 序 ]
阿狸的打字机:非常牛的 AC 自动机题. 暴力 先考虑在暴力的情况下,我们如何计算 \(x\) 匹配 \(y\) 的次数.显然,我们会模拟往 \(y\) 里加字符的过程,在此过程中做 KMP 进行匹配 ...
- mybatis之生命周期及作用域
SqlSessionFactoryBuilder 一旦创建了SqlSessionFactory之后就没有作用了 局部变量 SqlSessionFactory 可以理解为数据库的连接池 SqlSessi ...
- 网络编程之TCP、UDP和URL
TCP实现聊天 客户端 连接服务器Socket 发送消息 package com.yeyue.lesson2; import java.io.IOException; import java.i ...
- Ubuntu Linux部署DeepSeek(转载用于学习)
合集 - DeepSeek(4) 1.Ubuntu Linux部署DeepSeek02-06 2.Windows11本地部署DeepSeek加速02-073.DeepSeek部署本地知识库02-084 ...
- 理解ID3决策树
决策树是一个树形结构,类似下面这样: 上图除了根节点外,有三个叶子节点和一个非叶子节点. 在解决分类问题的决策树中,叶子节点就表示所有的分类,比如这里的分类就有3种:无聊时阅读的邮件.需及时处理的邮件 ...