2010-06-08 66 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