Lind.DDD.Domain領域(yu)模型介紹
Lind.DDD.Domain位于(yu)Lind.DDD核心項目(mu)中(zhong),它(ta)主(zhu)(zhu)要(yao)面(mian)向領域實(shi)體(ti)而(er)設(she)計,由(you)一個(ge)IEntity的(de)(de)標識接(jie)口(kou),EntityBase基類(lei)(lei)和N個(ge)Entity實(shi)體(ti)類(lei)(lei)組成,其中(zhong)IEntity主(zhu)(zhu)要(yao)用(yong)(yong)來(lai)(lai)標識,在(zai)倉(cang)儲操作(zuo)時(shi)(shi),用(yong)(yong)它(ta)來(lai)(lai)表(biao)明操作(zuo)的(de)(de)實(shi)體(ti)范圍和約束;EntityBase定義(yi)了(le)(le)幾個(ge)公(gong)用(yong)(yong)的(de)(de)屬(shu)性(xing),為(wei)了(le)(le)避免代(dai)碼的(de)(de)重(zhong)復(fu),特意將狀(zhuang)態(tai),插入時(shi)(shi)間和更新時(shi)(shi)間定義(yi)到了(le)(le)EntityBase里,而(er)為(wei)何不(bu)(bu)將主(zhu)(zhu)鍵(jian)定義(yi)進來(lai)(lai)呢,主(zhu)(zhu)要(yao)考慮到主(zhu)(zhu)鍵(jian)的(de)(de)類(lei)(lei)型(xing)是為(wei)確實(shi)的(de)(de),還(huan)有(you)就是不(bu)(bu)同類(lei)(lei)型(xing)的(de)(de)主(zhu)(zhu)鍵(jian)可能(neng)(neng)需(xu)要(yao)實(shi)現(xian)不(bu)(bu)同的(de)(de)特性(xing),如MongoDB的(de)(de)主(zhu)(zhu)鍵(jian)可能(neng)(neng)是BsonID或者需(xu)要(yao)為(wei)它(ta)添加BsonId這個(ge)特性(xing),所(suo)以將主(zhu)(zhu)鍵(jian)從EntityBase中(zhong)拿出(chu)來(lai)(lai),誰需(xu)要(yao)就去實(shi)現(xian)它(ta),也是符合面(mian)向對象的(de)(de)原則的(de)(de).
下面我們來看一下Lind.DDD.Domain設計實(shi)體的代碼(ma)
一 IEntity實體標識接(jie)口(kou),所有poco實體都繼承它
/// <summary> /// 實體類標示接(jie)口 /// </summary> public interface IEntity { }
二 EntityBase實(shi)體基類,具(ju)體實(shi)體基類要繼承它(ta),共享它(ta)的屬性
/// <summary> /// 領域模(mo)(mo)型(xing)(xing),實體模(mo)(mo)型(xing)(xing)基類,它可能有多種持久化(hua)方式,如DB,File,Redis,Mongodb,XML等 /// Lind.DDD框架的領域模型與數據(ju)庫實體(ti)合二(er)為一 /// </summary> [PropertyChangedAttribute] public abstract class EntityBase : // ContextBoundObject,//屬性(xing)變(bian)(bian)化(hua)跟蹤,這(zhe)(zhe)個(ge)可以在具體的實體上添加,需要記錄它的set變(bian)(bian)化(hua),就(jiu)添加這(zhe)(zhe)個(ge)特性(xing) IEntity, INotifyPropertyChanged { #region Contructors /// <summary> /// 實(shi)體初始化 /// </summary> public EntityBase() : this(Status.Normal, DateTime.Now, DateTime.Now) { } /// <summary> /// 帶參數的初始化 /// </summary> /// <param name="status">狀態</param> /// <param name="updateDateTime">更新(xin)日期</param> /// <param name="createDateTime">插入日期</param> public EntityBase(Status status, DateTime updateDateTime, DateTime createDateTime) { this.DataStatus = Status.Normal; this.DataUpdateDateTime = DateTime.Now; this.DataCreateDateTime = DateTime.Now; this.PropertyChanged += EntityBase_PropertyChanged; } #endregion #region Properties /// <summary> /// 建立(li)時間(jian) /// </summary> [XmlIgnore, DataMember(Order = 3), XmlElement(Order = 3), DisplayName("建立時間"), Required] public DateTime DataCreateDateTime { get; set; } /// <summary> /// 更新(xin)時(shi)間(jian) /// </summary> [XmlIgnore, DataMember(Order = 2), XmlElement(Order = 2), DisplayName("更新時(shi)間"), Required] public DateTime DataUpdateDateTime { get; set; } /// <summary> /// 實體狀態 /// </summary> [XmlIgnore, DataMember(Order = 1), XmlElement(Order = 1), DisplayName("狀態"), Required] public Status DataStatus { get; set; } #endregion #region Methods /// <summary> /// 拿到(dao)實(shi)體驗證的結果列表(biao) /// 結果為null或者Enumerable.Count()==0表(biao)達驗(yan)證成功(gong) /// </summary> /// <returns></returns> public IEnumerable<RuleViolation> GetRuleViolations() { var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray(); foreach (var i in properties) { var attr = i.GetCustomAttributes(); foreach (var a in attr) { var val = (a as ValidationAttribute); if (val != null) if (!val.IsValid(i.GetValue(this))) { yield return new RuleViolation(val.ErrorMessage, i.Name); } } } } #endregion #region PropertyChangedEventHandler Events /// <summary> /// 屬性值(zhi)變更(geng)事(shi)件,外部可以直(zhi)接訂閱它 /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 事件(jian)實例 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void EntityBase_PropertyChanged(object sender, PropertyChangedEventArgs e) { Console.WriteLine("基類EntityBase屬性:{0},值:{1}", e.PropertyName, sender.GetType().GetProperty(e.PropertyName).GetValue(sender)); } /// <summary> /// 觸發事件,寫在每個(ge)屬(shu)性的(de)(de)set塊中(zhong)CallerMemberName特性表示(shi)當前塊的(de)(de)屬(shu)性名 /// </summary> /// <param name="propertyName"></param> protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #endregion }
三 主鍵為整形的實體(ti)基(ji)類(lei)Entity,它(ta)(ta)繼(ji)承(cheng)了EntityBase,實現了自(zi)己的主鍵,所以主鍵為整形的實體(ti),都(dou)要繼(ji)承(cheng)它(ta)(ta)
/// <summary> /// 主鍵(jian)為int類型(xing)的實(shi)體基類 /// </summary> public abstract class Entity : EntityBase { /// <summary> /// 標識列 /// </summary> [DisplayName("編號"), Column("ID"), Required] public int Id { get; set; } }
四 主鍵為(wei)string類型(xing)的實體基類為(wei)NoSqlEntity,起初為(wei)了實現Mongodb表的ObjectID主鍵而設計(ji)的,其(qi)它的數據(ju)庫如果表的主鍵為(wei)字符串,也可以(yi)直(zhi)接繼承它
/// <summary> /// mongodb,xml,redis實體基(ji)類 /// 主鍵類型為string /// </summary> public abstract class NoSqlEntity : EntityBase { public NoSqlEntity() { this.Id = ObjectId.GenerateNewId().ToString(); } /// <summary> /// 標識列(lie) /// </summary> [BsonId] [BsonRepresentation(BsonType.ObjectId)] [DataMember(Order = 0), XmlElement(Order = 0), DisplayName("編號"), Column("ID"), Required] public string Id { get; set; } /// <summary> /// 返回mongodb實體的鍵值對(dui) /// </summary> public IEnumerable<KeyValuePair<string, object>> GetProperyiesDictionary() { var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(i => i.Name != "Id") .ToArray(); foreach (var i in properties) yield return new KeyValuePair<string, object>(i.Name, i.GetValue(this)); } }
在NoSqlEntity抽象類里,我們看到了共有方法GetProperyiesDictionary(),它(ta)主要功能是將表(biao)中所有屬性(xing)和它(ta)的(de)值(zhi)以(yi)(yi)鍵值(zhi)對(dui)的(de)方式(shi)返(fan)回一個枚(mei)舉集合,我們有時在倉儲類中可以(yi)(yi)直接(jie)使用(yong)這個方法,向Mongodb集成了對(dui)這種類型的(de)支持,可以(yi)(yi)方便的(de)實現對(dui)表(biao)
的添加與更新!
Lind.DDD.Domain實體模型(xing)除了定(ding)義實體外(wai),還(huan)提供了實體屬性的(de)變更跟蹤功(gong)能,即當一(yi)個屬性值發生(sheng)變化時(shi)(set 方法被觸發時(shi))我(wo)們可以跟蹤到它,并進行相應(ying)的(de)操作(zuo),一(yi)般地,我(wo)們會在使(shi)用者層(ceng),添加一(yi)種事(shi)件(jian),使(shi)用者只要(yao)訂閱(yue)了這種事(shi)件(jian),就可以實現對
跟蹤實(shi)體的(de)操作,如把(ba)變更保存(cun)到文件(jian),或(huo)者(zhe)直(zhi)接(jie)入(ru)庫等等!
更多的介紹,請查看Lind.DDD源碼框架的介紹