首页 > DDD领域驱动设计之聚合、实体、值对象

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

关于具体需求,请看前面的博文: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
{/// /// 项目基类/// public abstract class ProjectBase : EntityBase, IAggregateRoot{protected ProjectBase(){this.ND = DateTime.Now.Year;this.CJSJ = DateTime.Now;this.WH = new DocumentNumber();}/// /// 安排批次/// public int APPC { get; set; }/// /// 项目名称/// public string XMMC { get; set; }/// /// 项目编号/// public string XMBH { get; internal set; }/// /// 年度/// public int ND { get; set; }/// /// 文号/// public DocumentNumber WH { get; set; }/// /// 创建时间/// public DateTime CJSJ { get; set; }/// /// 下发行政区名称/// public string XFXZQMC { get; set; }/// /// 下发行政区代码/// public string XFXZQDM { get; set; }/// /// 行政区名称/// public string XZQMC { get; set; }/// /// 行政区代码/// public string XZQDM { get; set; }/// /// 备注/// public string BZ { get; set; }/// /// 指标级别/// public IndicatorGrade ZBJB { get; set; }/// /// 附件id/// public decimal ATTACHID { get; set; }/// /// 项目状态/// public ProjectStauts Status { get; set; }/// /// 业务代码/// protected abstract string BussinessCode { get; }/// /// 登记/// /// public virtual void Register(){this.XMBH = this.BussinessCode + SeqGeneratr.Generate();}/// /// 是否可以更新或者删除/// /// 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
{/// /// 计划指标/// public class PlanIndicator : ProjectBase{public PlanIndicator(){IndicatorArea = new IndicatorArea();}protected override string BussinessCode{get { return "103101"; }}/// /// 指标面积/// public IndicatorArea IndicatorArea{get;set;}public override IEnumerable 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
{/// /// 计划安排/// public class PlanArrange : ProjectBase{public PlanArrange(){JHSY = new IndicatorArea();SJSY = new IndicatorArea();}protected override string BussinessCode{get { return "103102"; }}/// /// 计划使用面积/// public IndicatorArea JHSY{get;set;}/// /// 实际使用面积/// public IndicatorArea SJSY{get;set;}/// /// 剩余面积/// public IndicatorArea SY{get{return JHSY - SJSY;}}/// /// 用地类别/// public string XMYDLB { get; set; }public override IEnumerable 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
{/// /// 文号/// public class DocumentNumber : ValueObject, 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);}}/// /// 发文机关代字/// public string Code { get; set; }/// /// 年份/// public string Year { get; set; }private string order;/// /// 顺序号/// 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
{/// /// 指标面积/// public class IndicatorArea : ValueObject{/// /// 新增建设用地/// public decimal XZJSYD{get{return NYD + WLYD;}}/// /// 农用地/// public decimal NYD { get; set; }/// /// 耕地/// public decimal GD { get; set; }/// /// 未利用地/// public decimal WLYD { get; set; }/// /// 将公顷转换成亩/// /// public IndicatorArea HectareToMu(){return new IndicatorArea{GD = this.GD * 15,NYD = this.NYD * 15,WLYD = this.WLYD * 15,};}/// /// 重载加法运算符/// /// /// /// 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 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 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
{/// /// 指标级别/// public enum IndicatorGrade{/// /// 国家/// [Description("国家")]Country,/// /// 省级/// [Description("省级")]Province,/// /// 市级/// [Description("市级")]City,/// /// 县级/// [Description("县级")]County,}
}
using System.ComponentModel;namespace DDD.Domain
{/// /// 项目状态/// public enum ProjectStauts{/// /// 默认状态,已登记/// Default,/// /// 已下发/// Sent,}
}

  

  

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

更多相关:

  • 关于Graphics也有了基本了解下面想说的的是学这个东东干什么呢,到底如何应用目前常见应用1、验证码(参照网上的)2、打印排版(会提到关于条形码大小设置)3、自定义控件 一、验证码 1 class ValidateCode 2 { 3 #region 定义和初始化配置字段 4...

  •   最近公司在做一个医疗项目,使用WinForm界面作为客户端交互界面。在整个客户端解决方案中。使用了MVP模式实现。由于之前没有接触过该设计模式,所以在项目完成到某个阶段时,将使用MVP的体会写在博客里面。   所谓的MVP指的是Model,View,Presenter。对于一个UI模块来说,它的所有功能被分割为三个部分,分别通过M...

  • TPL Dataflow是微软面向高并发应用而推出的新程序库。借助于异步消息传递与管道,它可以提供比线程池更好的控制。本身TPL库在DataflowBlock类中提供了不少扩展函数,用起来还是非常方便的,但感觉还是不够全(当然,MS没必要设计大而全的接口),前段时间写个小程序的时候用到了它,当时顺便写了几个扩展函数,这里记录一下,如果...

  • 前言       写系列文章的时候[前言]部分变得无言了,可能来得顺利了点吧: ) 本章中提供的封装均是我用笨办法从<>和<>中拷贝出来并参照VC++代码进行整理的,主要是针对HikServ...

  • 在.Net Framework中,配置文件一般采用的是XML格式的,.NET Framework提供了专门的ConfigurationManager来读取配置文件的内容,.net core中推荐使用json格式的配置文件,那么在.net core中该如何读取json文件呢?1、在Startup类中读取json配置文件1、使用Confi...

  •   1 public class FrameSubject extends JFrame {   2    3   …………..   4    5   //因为无法使用多重继承,这儿就只能使用对象组合的方式来引入一个   6    7   //java.util.Observerable对象了。   8    9   DateSub...

  • 本案例主要说明如何使用NSwag 工具使用桌面工具快速生成c# 客户端代码、快速的访问Web Api。 NSwagStudio 下载地址 比较强大、可以生成TypeScript、WebApi Controller、CSharp Client  1、运行WebApi项目  URL http://yourserver/swagger 然后...

  •   在绑定完Action的所有参数后,WebAPI并不会马上执行该方法,而要对参数进行验证,以保证输入的合法性.   ModelState 在ApiController中一个ModelState属性用来获取参数验证结果.   public abstract class ApiController : IHttpController,...

  • 1# 引用  C:AVEVAMarineOH12.1.SP4Aveva.ApplicationFramework.dll C:AVEVAMarineOH12.1.SP4Aveva.ApplicationFramework.Presentation.dll 2# 引用命名空间, using Aveva.Applicati...

  • IHostingEnviroment 获取环境相关洗洗 IsDevelopment()、IsStaging()、IsProduction() 分别为:开发、准生产、生产环境 IsEnviroment("Uat") 自定义环境,比如自定义Uat环境 新建: appsettings.Uat.json文件 {"Enviroment":...

  • 七. DockPanel DockPanel定义一个区域,在此区域中,您可以使子元素通过描点的形式排列,这些对象位于 Children 属性中。停靠面板其实就是在WinForm类似于Dock属性的元 素。DockPanel会对每个子元素进行排序,并停靠在面板的一侧,多个停靠在同侧的元素则按顺序排序。     如果将 LastChild...

  • 该链接有导入,导出源码,我的代码有下链接改写,完善而成的, http://www.cnblogs.com/colder/p/3611906.html using System;using System.Collections.Generic;using System.Linq;using System.Web;using System...

  • 转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ 对于SharePoint中已经是Record的Item,我们想要修改他的属性,这在UI界面是无法完成的: 这时需要通过Records.BypassLocks API来完成。设计一个tool,利用Records.BypassLocks...

  • C# async await 学习笔记1(http://www.cnblogs.com/siso/p/3691059.html)  提到了ThreadId是一样的,突然想到在WinForm中,非UI线程是无法直接更新UI线程上的控件的问题。 于是做了如下测试: using System; using System.Collectio...