關於具體需求,請看前面的博文: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,
}
}
