关于具体需求,请看前面的博文:DDD领域驱动设计实践篇之如何提取模型,下面是具体的实体、聚合、值对象的代码,不想多说什么是实体、聚合等概念,相信理论的东西大家已经知晓了。本人对DDD表示好奇,没有在真正项目实践过,甚至也没有看过真正的DDD实践的项目源码,处于极度纠结状态,甚至无法自拔,所以告诫DDD爱好者们,如果要在项目里面实践DDD,除非你对实体建模和领域职责非常了解(很多时候会纠结一些逻辑放哪里好,属于设计问题)以及你的团队水平都比较高认同DDD,否则请慎重。。。勿喷!

代码在后,请先看DEMO结果图

1、聚合的基类,注意,几乎属性都是拼音首字母命名,勿喷哈,不要跑题!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DDD.Infrastructure;
using DDD.Infrastructure.Domain;namespace DDD.Domain
{/// <summary>/// 项目基类/// </summary>public abstract class ProjectBase : EntityBase, IAggregateRoot{protected ProjectBase(){this.ND = DateTime.Now.Year;this.CJSJ = DateTime.Now;this.WH = new DocumentNumber();}/// <summary>/// 安排批次/// </summary>public int APPC { get; set; }/// <summary>/// 项目名称/// </summary>public string XMMC { get; set; }/// <summary>/// 项目编号/// </summary>public string XMBH { get; internal set; }/// <summary>/// 年度/// </summary>public int ND { get; set; }/// <summary>/// 文号/// </summary>public DocumentNumber WH { get; set; }/// <summary>/// 创建时间/// </summary>public DateTime CJSJ { get; set; }/// <summary>/// 下发行政区名称/// </summary>public string XFXZQMC { get; set; }/// <summary>/// 下发行政区代码/// </summary>public string XFXZQDM { get; set; }/// <summary>/// 行政区名称/// </summary>public string XZQMC { get; set; }/// <summary>/// 行政区代码/// </summary>public string XZQDM { get; set; }/// <summary>/// 备注/// </summary>public string BZ { get; set; }/// <summary>/// 指标级别/// </summary>public IndicatorGrade ZBJB { get; set; }/// <summary>/// 附件id/// </summary>public decimal ATTACHID { get; set; }/// <summary>/// 项目状态/// </summary>public ProjectStauts Status { get; set; }/// <summary>/// 业务代码/// </summary>protected abstract string BussinessCode { get; }/// <summary>/// 登记/// </summary>/// <param name="seq"></param>public virtual void Register(){this.XMBH = this.BussinessCode + SeqGeneratr.Generate();}/// <summary>/// 是否可以更新或者删除/// </summary>/// <returns></returns>public virtual bool CanUpdate(){return this.ZBJB == IndicatorGrade.Country || this.XFXZQDM == this.XZQDM || this.Status == ProjectStauts.Default;}public void Send(){this.Status = ProjectStauts.Sent;}}
}

2、聚合1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DDD.Infrastructure;
using DDD.Infrastructure.Domain;namespace DDD.Domain.Indicator
{/// <summary>/// 计划指标/// </summary>public class PlanIndicator : ProjectBase{public PlanIndicator(){IndicatorArea = new IndicatorArea();}protected override string BussinessCode{get { return "103101"; }}/// <summary>/// 指标面积/// </summary>public IndicatorArea IndicatorArea{get;set;}public override IEnumerable<BusinessRule> Validate(){if (this.IndicatorArea.GD > this.IndicatorArea.NYD){yield return new BusinessRule("IndicatorArea.GD", "耕地面积不能大于农用地面积");}}public override void Register(){if (this.ZBJB == IndicatorGrade.Country){this.Send();}base.Register();}}
}

3、聚合2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DDD.Infrastructure;
using DDD.Infrastructure.Domain;namespace DDD.Domain.Arrange
{/// <summary>/// 计划安排/// </summary>public class PlanArrange : ProjectBase{public PlanArrange(){JHSY = new IndicatorArea();SJSY = new IndicatorArea();}protected override string BussinessCode{get { return "103102"; }}/// <summary>/// 计划使用面积/// </summary>public IndicatorArea JHSY{get;set;}/// <summary>/// 实际使用面积/// </summary>public IndicatorArea SJSY{get;set;}/// <summary>/// 剩余面积/// </summary>public IndicatorArea SY{get{return JHSY - SJSY;}}/// <summary>/// 用地类别/// </summary>public string XMYDLB { get; set; }public override IEnumerable<BusinessRule> Validate(){if (this.JHSY.GD > this.JHSY.NYD){yield return new BusinessRule("JHSY.GD", "计划使用中,耕地面积不能大于农用地面积");}if (this.SJSY.GD > this.SJSY.NYD){yield return new BusinessRule("SJSY.GD", "实际使用中,耕地面积不能大于农用地面积");}if (string.IsNullOrEmpty(this.XMYDLB)){yield return new BusinessRule("XMYDLB", "项目用地类别不允许为空");}}}
}

4、值对象1

using System;
using DDD.Infrastructure.Domain;namespace DDD.Domain
{/// <summary>/// 文号/// </summary>public class DocumentNumber : ValueObject<DocumentNumber>, ICloneable{public static readonly string LeftYearChar = "〔";public static readonly string RightYearChar = "〕";public DocumentNumber() {}public DocumentNumber(string wh) {try{this.Code = wh.Substring(0, wh.IndexOf(LeftYearChar));this.Year = wh.Substring(wh.IndexOf(LeftYearChar), wh.IndexOf(RightYearChar) - this.Code.Length + 1);this.Order = wh.Replace(this.Code + this.Year, "");this.Year = this.Year.Replace(LeftYearChar, "").Replace(RightYearChar, "");}catch(Exception ex){throw new InvalidCastException("文号格式不正确", ex);}}/// <summary>/// 发文机关代字/// </summary>public string Code { get; set; }/// <summary>/// 年份/// </summary>public string Year { get; set; }private string order;/// <summary>/// 顺序号/// </summary>public string Order{get{if (!string.IsNullOrEmpty(order) && !order.Contains("号")){order += "号";}return order;}set{order = value;}}public override string ToString(){if (string.IsNullOrEmpty(Code) && string.IsNullOrEmpty(Year) && string.IsNullOrEmpty(order)){return string.Empty;}return this.Code + LeftYearChar + Year + RightYearChar + Order;}public static implicit operator DocumentNumber(string wh){return new DocumentNumber(wh);}public object Clone(){return this.MemberwiseClone();}}
}

5、值对象2

using DDD.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DDD.Infrastructure.Domain;namespace DDD.Domain
{/// <summary>/// 指标面积/// </summary>public class IndicatorArea : ValueObject<IndicatorArea>{/// <summary>/// 新增建设用地/// </summary>public decimal XZJSYD{get{return NYD + WLYD;}}/// <summary>/// 农用地/// </summary>public decimal NYD { get; set; }/// <summary>/// 耕地/// </summary>public decimal GD { get; set; }/// <summary>/// 未利用地/// </summary>public decimal WLYD { get; set; }/// <summary>/// 将公顷转换成亩/// </summary>/// <returns></returns>public IndicatorArea HectareToMu(){return new IndicatorArea{GD = this.GD * 15,NYD = this.NYD * 15,WLYD = this.WLYD * 15,};}/// <summary>/// 重载加法运算符/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static IndicatorArea operator +(IndicatorArea a, IndicatorArea b){return new IndicatorArea{GD = a.GD + b.GD,NYD = a.NYD + b.NYD,WLYD = a.WLYD + b.WLYD,};}/// <summary>/// 重载减法运算符/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static IndicatorArea operator -(IndicatorArea a, IndicatorArea b){return new IndicatorArea{GD = a.GD - b.GD,NYD = a.NYD - b.NYD,WLYD = a.WLYD - b.WLYD,};}public static IndicatorArea Sum(IEnumerable<IndicatorArea> query){return new IndicatorArea{GD = query.Sum(t => t.GD),NYD = query.Sum(t => t.NYD),WLYD = query.Sum(t => t.WLYD),};}}
}

  

6、枚举

using System.ComponentModel;namespace DDD.Domain
{/// <summary>/// 指标级别/// </summary>public enum IndicatorGrade{/// <summary>/// 国家/// </summary>[Description("国家")]Country,/// <summary>/// 省级/// </summary>[Description("省级")]Province,/// <summary>/// 市级/// </summary>[Description("市级")]City,/// <summary>/// 县级/// </summary>[Description("县级")]County,}
}

using System.ComponentModel;namespace DDD.Domain
{/// <summary>/// 项目状态/// </summary>public enum ProjectStauts{/// <summary>/// 默认状态,已登记/// </summary>Default,/// <summary>/// 已下发/// </summary>Sent,}
}

  

  

转载于:https://www.cnblogs.com/liubiaocai/p/3938192.html

DDD领域驱动设计之聚合、实体、值对象相关推荐

  1. DDD领域驱动设计实战 - 创建实体身份标识的常用策略

    从简单到复杂依次为: 3.1.1 用户提供唯一标识 这时用户将输入一些可识别的数值或符号,或从已有标识中选其一,然后创建实体对象.这是一种非常简单方案,但也可能变得复杂. 由于需用户自己生成高质量的标 ...

  2. DDD领域驱动设计之领域基础设施层

    1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 其实这里说的基础设施层只是领域层的一些接口和基类而已,没有其他的如日子工具等代码,仅仅是为了说明领域层的一些基础 ...

  3. DDD 领域驱动设计-三个问题思考实体和值对象(续)

    上一篇:DDD 领域驱动设计-三个问题思考实体和值对象 说实话,整理现在这一篇博文的想法,在上一篇发布出来的时候就有了,但到现在才动起笔来,而且写之前又反复读了上一篇博文的内容及评论,然后去收集资料, ...

  4. 浅谈我对DDD领域驱动设计的理解

    从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...

  5. C#进阶系列——DDD领域驱动设计初探(五):AutoMapper使用

    前言:前篇搭建了下WCF的代码,就提到了DTO的概念,对于为什么要有这么一个DTO的对象,上章可能对于这点不太详尽,在此不厌其烦再来提提它的作用: 从安全上面考虑,领域Model都带有领域业务,让Cl ...

  6. [转]浅析DDD(领域驱动设计)

    最近在做一些微服务相关的设计,内容包括服务的划分,Restful API的设计等.其中比较棘手的就是Service的职责划分:如何抽象具有统一业务范畴的Model,使其模块化,又如何高度提炼并组合多模 ...

  7. 浅析DDD(领域驱动设计)

    最近在做一些微服务相关的设计,内容包括服务的划分,Restful API的设计等.其中比较棘手的就是Service的职责划分:如何抽象具有统一业务范畴的Model,使其模块化,又如何高度提炼并组合多模 ...

  8. DDD 领域驱动设计落地实践:六步拆解 DDD

    引言 相信通过前面几篇文章的介绍,大家对于 DDD 的相关理论以及实践的套路有了一定的理解,但是理解 DDD 理论和实践手段是一回事,能不能把这些理论知识实际应用到我们实际工作中又是另外一回事,因此本 ...

  9. 从EF三层 到 DDD领域驱动设计(1)--------------数据操作

    前言: 一路走来,从单片机到C#,从电子行业到计算机行业,技术是不断提高,但是身体确不断变差,本来高新的工作也不得不辞掉,改到一家国企过着咸鱼般,但很爽的生活. 最近的金砖比较忙,刚忙完金砖的事,就有 ...

最新文章

  1. 用C#去除代码的SourceSafe管理
  2. 区块链以及区块链技术总结
  3. WebView通过loadDataWithBaseURL加载本地页面卡死
  4. FTP服务器的搭建及简单应用
  5. rapter求n的阶乘流程图_RAPTOR程序设计例题参考答案
  6. centos7 kickstart 使用小结
  7. 单元测试代码:SpringTest+JUnit
  8. EM(期望极大化)算法及其推广
  9. Linux基金会亚太区与开源中国达成战略合作 共同推动中国开源人才培养
  10. java 定义构造器_java的构造器定义以及使用
  11. php解析url的三种方法举例
  12. python从零开始学爬虫_从零开始学爬虫(爬取豆瓣),一看就会
  13. 易维帮助台:让IT运维服务与企业业务发展需求高度融合
  14. android 7.0 截图,Android,_7.0系统拍照后,使用系统截图功能,截图保存时崩溃如何解决,Android - phpStudy...
  15. [转]写一个块设备驱动(第七章)
  16. ADSL接入路由,电脑共享上网
  17. 安装SQL server出现“启用windows功能NetFx3”错误
  18. 【2016年第1期】关于我国农业大数据中心建设的设想
  19. wmctf2022 两题PvsZ
  20. 虚拟现实(VR)、增强现实(AR)、混合现实(MR)

热门文章

  1. c语言日期星期程序,C语言程序设计: 输入年月日 然后输出是星期几
  2. abaqus切削为什么没有切屑_基于ABAQUS的高速切削切屑形成过程的有限元模拟
  3. 侏罗纪怪兽世界怎么登陆服务器未响应,全金属怪物进不去怎么解决
  4. Fins TCP协议
  5. python 点云las、laz文件的读取、写入、压缩
  6. 和12岁小同志搞创客开发:如何选择合适的控制器?
  7. WifiP2pService工作流程
  8. 【TensorFlow2.0】(2) 创建tensor的方法
  9. Matlab实现 sift 特征匹配(代码源自网络)
  10. C++ OpenCV创建xml,yml文件(图像)列表程序