2010-06-08 70 views
3

我測試了使用NHibernate與一個完全不知道它的域並且不想屈服於任何限制的困難。NHibernate映射,沒有空的構造函數和沒有setter

在網上發現的很多例子中,被映射的域是貧血域的另一個例子,對象離簡單的數據持有者並不遙遠。當然,這使得映射變得簡單和全面,它可能會吸引以數據爲中心的人/情境,但我不喜歡聽到我腦海中的聲音說「C也有結構,你知道嗎?」,「類不是隻是很花哨的命名空間,你知道嗎?「,或者」你爲什麼不用CREATE TABLE?「。

但是回到NHibernate。 NHibernate迫使我使虛擬屬性能夠代理它們進行延遲加載。這是我不介意的,因爲我也可能需要它們作爲虛擬的AOP。 我不滿意的侷限性是需要一個空的構造函數以及對setter /屬性的需要。我希望我的實體能夠在有效狀態下創建,並且大部分時間表示沒有空的構造函數。 我也不想公開收集屬性的setters,通常的原因。噢,以及那些不應該直接改變的屬性的setter。

考慮這個簡化和做作聚集在一個域模型的地方:

public class ShoppingCartItem 
{ 
    private readonly Product product; 

    public ShoppingCartItem(Product product, int quantity) 
    { 
     if(quantity <= 0) 
      throw new ArgumentOutOfRangeException("quantity"); 
     this.product = product; 
     this.quantity = quantity; 
    } 
    public virtual Product Product 
    { 
     get { return product; } 
    } 
    private int quantity; 
    public virtual int Quantity 
    { 
     get { return quantity; } 
     set 
     { 
      if(value <= 0) 
       throw new ArgumentOutOfRangeException("value"); 
      quantity = value; 
    } 

    public virtual Money TotalPrice 
    { 
     get { return product.Price * quantity; } 
    } 
} 

public class ShoppingCart : Entity 
{ 
    private readonly IDictionary<Product, ShoppingCartItem> items = 
     new Dictionary<Product, ShoppingCartItem>(); 
    private readonly ISet<DiscountCoupon> discountCoupons = 
     new HashSet<DiscountCoupon>(); 

    public virtual IEnumerable<ShoppingCartItem> Items 
    { 
     get { return items.Values; } 
    } 

    public virtual IEnumerable<DiscountCoupon> DiscountCoupons 
    { 
     get { return discountCoupons; } 
    } 

    public virtual void AddProduct(Product product) 
    { 
     ShoppingCartItem item; 
     if(items.TryGetValue(product, out item)) 
      item.Quantity++; 
     else 
      items.Add(product, new ShoppingCartItem(product, 1)); 
    } 

    public virtual void RemoveProduct(Product product) 
    { 
     ShoppingCartItem item; 
     if(!items.TryGetValue(product, out item)) 
      throw new ArgumentException("product"); 

     if(item.Quantity == 1) 
      items.Remove(product); 
     else 
      item.Quantity--; 
    } 

    public virtual int AddDiscountCoupon(DiscountCoupon coupon) 
    { 
     discountCoupons.Add(coupon); 
    } 

    public virtual int RemoveDiscountCoupon(DiscountCoupon coupon) 
    { 
     discountCoupons.Remove(coupon); 
    } 

    public virtual Money CalculatePrice() 
    { 
     // Missing complex discount logic 
     return items.Values.Sum(item => item.TotalPrice); 
    } 
} 

大多數屬性都沒有二傳手,有沒有空的構造函數在望。集合不直接干涉,而是通過專門的方法。我可以使用NHibernate的可擴展性來映射這個嗎?或者我想再次敲一顆螺絲?或兩者?

回答

4

首先可以使空的構造私有,這樣其他人可以訪問它。 NH仍然能夠得到它。

第二次關閉NH可以訪問你的屬性,但是你想要的。

access =「backfield」用於公共虛擬產品Product {get;私人設置; }

訪問=「field.pascalcase米下劃線」爲m_Product

訪問=「field.pascalcase下劃線」爲_產品

還有其他的訪問策略,我敢肯定,你可以即使創造你自己的需要。

+0

事實上,訪問策略並不總是需要明確定義的 – Jaguar 2010-06-08 16:14:35

+1

這是不完全正確的。構造函數應該受到保護。從異常:「NHibernate.InvalidProxyTypeException:下列類型不能用作代理: ClassA:類型應該有一個可見(公共或受保護的)無參數構造函數」。文檔(4.1.2)說:「類必須有一個默認的構造函數(可能是非公有的)」 – esegura 2010-12-21 16:02:49