首页 > 代码库 > 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{    /// <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,    }}

  

  

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