再論Domain與Infrastructure
在面向領域的設計中,領域層(Domain)實現上是位於最底層的,其它層有對它的引用,包括基礎設施層(Infrastructure)也是去引用領域層的,我認為,這是對的,事實上,在Domain中會規定如何去進行數據持久化的操作,包括方法名,方法簽名等等,而采用哪種架構去實現這種持久化的方法則是Infrastructure層需要做的,這種設計絕對是把領域,業務放在第一位的,完全符合Eric 的DDD。
Domain.Core Layer & Domain Layer
我們在進行軟件設計時,一個習慣就是把僅供代碼抽象出來,這是對的,也是符合標准的,對於domain層我們會把與具體領域無關的代碼抽象成一個domain.core,這個項目位於整個DDD解決方案的最底層,而具體的domain則會引入它,看一下我們的DDD中的domain層
domain.core中有數據持久化的規范,規約實現Specification及一些公用的功能代碼。
具體的domain項目中包括三部分內容,具體業務規范(如產品業務規范Products),數據模型POCO實體,用於網絡傳輸的DTO實體(這部分可以單拿出來,本例直接放在了實體層),我們先來看一下products這個業務規范:
IProductRepository:它是產品實體的數據持久化規范,Infrastructure層會去實現它,這里不會關心Infrastructure是采用linq to sql還是ef,我只規定要做什么,至少怎么去做,由Infrastructure自己去決定!
public interface IProductRepository : IExtensionRepository<Product> { /// <summary> /// 獲取產品列表 /// </summary> /// <returns></returns> IQueryable<Product> GetProduct(); /// <summary> /// 建立產品 /// </summary> void AddProduct(Product entity); /// <summary> /// 修改產品 /// </summary> void ModifyProduct(System.Linq.Expressions.Expression<Action<Product>> entity); }
ProductSpecification:這是一個與業務息息相關的規約類,它會根據具體業務去設計每一個業務的具體規約
/// <summary> /// 通過用戶信息得到他的訂單列表 /// </summary> public class ProductSpecification : Specification<Product> { string _productName = default(string); public ProductSpecification(string productName) { _productName = productName; } public override Expression<Func<Product, bool>> SatisfiedBy() { Specification<Product> spec = new TrueSpecification<Product>(); if (string.IsNullOrWhiteSpace(_productName)) spec &= new DirectSpecification<Product>(o => o.ProductName.Contains(_productName)); return spec.SatisfiedBy(); } }
網絡傳輸對象DTO,它是在進行WEB通訊時為了減少網站負載,而提出的新的實體層,將與本服務有關的實體屬性提出,形成一個新的實體,這在SOA服務
中用的比較多。
[DataContract] public class ProductDTO { [DataMember] [DisplayName("商品ID")] public int ProductID { get; set; } [DataMember] [DisplayName("商品名稱")] public string ProductName { get; set; } [DataMember] [DisplayName("建立日期")] public System.DateTime CreateDate { get; set; } [DataMember] public int SaleCount { get; set; } [DataMember] public Nullable<int> ClickCount { get; set; } [DataMember] [DisplayName("產品描述")] public string Info { get; set; } [DataMember] public int UserID { get; set; } [DataMember] [DisplayName("銷售價格")] public decimal SalePrice { get; set; } [DataMember] [DisplayName("折扣")] public int Discount { get; set; } }
數據模型EDMX,這種模塊我們稱為entity frameworks模型,也叫EF模型,它可以把物理數據庫映射到EDMX文件中,它是以XML形式保存的,而我們
的POCO簡單數據實體也可以由工具自動生成,這些實體與原始數據表一一對應。ef poco 模型實體采用partial class方便開發人員以后對實體類進行擴展。
public partial class Product { public Product() { this.ProductDetail = new HashSet<ProductDetail>(); } public int ProductID { get; set; } public string ProductName { get; set; } public System.DateTime CreateDate { get; set; } public int SaleCount { get; set; } public Nullable<int> ClickCount { get; set; } public string Info { get; set; } public int UserID { get; set; } public decimal SalePrice { get; set; } public int Discount { get; set; } public System.DateTime UpdateDate { get; set; } public virtual User_Info User_Info { get; set; } public virtual ICollection<ProductDetail> ProductDetail { get; set; } }
最后,我們看一個domain與Infrastructure之間的數據通信,它們一般使用IOC容器進行實現,像Autofac和Unity都是不錯的選擇,而unity是一個強大的工具
集,它不僅包括IOC的功能,而且還提供了對AOP的實現!下次我們將着重介紹一下Unity在DDD中的使用,介請期待!