Отображение NHibernate без пустого конструктора и без установщиков - PullRequest
3 голосов
/ 08 июня 2010

Я проверяю, насколько сложно использовать NHibernate с доменом, который совершенно не знает об этом и не склонен учитывать любые ограничения.

Во многих примерах, которые я обнаружил в Интернете, сопоставляемый домен является еще одним примером анемичного домена, где объекты не уходят далеко от простых носителей данных. Конечно, это делает сопоставление простым и всем, и это может обратиться к лицам / ситуациям, ориентированным на данные, но мне не нравится слышать голоса в моей голове, которые говорят: «С тоже имеет структуру, понимаете?», «Классы не являются вы знаете, просто причудливые пространства имен? »или« Почему бы вместо этого не использовать CREATE TABLE? ».

Но вернемся к NHibernate. NHibernate заставляет меня сделать свойства виртуальными, чтобы иметь возможность прокси их для ленивой загрузки. Это то, что я не возражаю, так как они могут понадобиться как виртуальные для некоторых AOP. Ограничения, которые меня не устраивают, - это необходимость в пустом конструкторе и необходимость в установщиках / свойствах. Я хочу, чтобы мои сущности были созданы в допустимом состоянии, и в большинстве случаев это означает, что нет пустого конструктора. Я также не хочу выставлять сеттеры для свойств коллекции по обычным причинам. Да, и сеттеры для атрибутов, которые не должны изменяться напрямую.

Рассмотрим этот упрощенный и надуманный агрегат в доменной модели где-то:

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, чтобы отобразить это? Или я снова пытаюсь вбить винт? Или оба?

Ответы [ 2 ]

8 голосов
/ 08 июня 2010

Хорошо, вы можете установить частные / внутренние / защищенные сеттеры для свойств / коллекций, и nhibernate загрузит их правильно (глава 4.1.1)

Конструктор должен иметь , но вы не обязаны делать его публичным (глава 4.1.2)

глава ссылка с последней http://sourceforge.net/projects/nhibernate/files/NHibernate/2.1.2GA/NHibernate-2.1.2.GA-reference.zip/download

4 голосов
/ 08 июня 2010

Прежде всего вы можете сделать пустой конструктор приватным, чтобы никто другой не мог получить к нему доступ. NH все еще сможет добраться до него.

Second off NH может получить доступ к вашей недвижимости, как вы хотите.

access = "backfield" используется для публичного виртуального продукта Product {get; приватный набор; }

access = "field.pascalcase-m-underscore" для m_Product

access = "field.pascalcase-underscore" для _Product

Существуют другие стратегии доступа, и я уверен, что вы даже можете создать свою собственную, если это будет необходимо.

...