DDD領域驅動設計之聚合、實體、值對象

關於具體需求,請看前面的博文:DDD領域驅動設計實踐篇之如何提取模型,下面是具體的實體、聚合、值對象的代碼,不想多說什麼是實體、聚合等概念,相信理論的東西你們已經知曉了。本人對DDD表示好奇,沒有在真正項目實踐過,甚至也沒有看過真正的DDD實踐的項目源碼,處於極度糾結狀態,甚至沒法自拔,因此告誡DDD愛好者們,若是要在項目裏面實踐DDD,除非你對實體建模和領域職責很是瞭解(不少時候會糾結一些邏輯放哪裏好,屬於設計問題)以及你的團隊水平都比較高認同DDD,不然請慎重。。。勿噴!html

 

代碼在後,請先看DEMO結果圖ide

 

一、聚合的基類,注意,幾乎屬性都是拼音首字母命名,勿噴哈,不要跑題!this

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;
        }
    }
}

二、聚合1spa

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();
        }
    }
}

三、聚合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", "項目用地類別不容許爲空");
            }
        }
    }
}

四、值對象1htm

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();
        }
    }
}

五、值對象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),
            };
        }
    }
}

  

六、枚舉blog

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,
    }
}
相關文章
相關標籤/搜索