3

我们的很多页面都使用自定义视图模型,这些模型本质上是 NHibernate 映射实体的缩减版本。

当您拥有一组全局实体时,重用以实体为中心的小块业务逻辑很简单,因为可以将逻辑添加到实体中。但是,一旦我们有了特定于视图的视图模型,这就会变得更加困难。

这是一个人为的例子:

// Entity
public class Sale : Entity
{
    public Guid Id { get; set; }
    public decimal Tax { get; set; }
    public decimal SalePrice { get; set; }
    public int TotalPrice
    {
        get { return Tax + SalePrice; }
    }
    ... more properties ...
}

// View model
public class SaleView
{
    public Guid Id { get; set; }
    public decimal Tax { get; set; }
    public decimal SalePrice { get; set; }
}

public class Controller
{
    public Action ViewSale(Guid id)
    {
        return Session.Query<Sale>()
            .Where(x => x.Id == id)
            .Select(x => new SaleView
                {
                    Id = x.Id,
                    Tax = x.Tax,
                    SalePrice = x.SalePrice
                });
    }
}

在此示例中,您使用哪些策略来重用当前在实体中执行的“TotalPrice”计算?

您可以在某处使“TotalPrice”成为静态方法,并让它接受税收和销售价格作为参数,但这会导致代码变得非常丑陋、不灵活,尤其是随着属性数量和属性之间关系的增长。您可以创建一个单独的“TotalPriceCalculator”类,但要处理 ViewModel,它需要接受实体和视图模型都实现的接口。这将导致重复代码的激增,因为我们现在必须将每个属性写出 3 次。还有什么可以做的?

4

1 回答 1

2

您可以定义一个总价政策,您可以将其注入您的实体和视图模型中。您注入总价格政策的事实使其更加灵活。您可以轻松实施其他策略。它看起来像这样:

public interface ITotalPricePolicy
{
    decimal TotalPrice(decimal tax, decimal salesPrice);
}

public class TotalPricePolicy : ITotalPricePolicy
{
    public decimal TotalPrice(decimal tax, decimal salesPrice)
    {
        return tax + salesPrice;
    }
}

public class Sale : Entity
{
    public Guid Id { get; set; }
    public decimal Tax { get; set; }
    public decimal SalePrice { get; set; }

    public decimal TotalPrice(ITotalPricePolicy totalPricePolicy)
    {
        return totalPricePolicy.TotalPrice(Tax, SalePrice);
    }
}

public class SaleViewModel
{
    private readonly ITotalPricePolicy _totalPricePolicy;

    public SaleViewModel(ITotalPricePolicy totalPricePolicy)
    {
        _totalPricePolicy = totalPricePolicy;
    }

    public Guid Id { get; set; }
    public decimal Tax { get; set; }
    public decimal SalePrice
    {
        get { return _totalPricePolicy.TotalPrice(Tax, SalePrice); }
    }
}

public class HomeController : Controller
{
    private readonly ITotalPricePolicy _totalPricePolicy;

    public HomeController(ITotalPricePolicy totalPricePolicy)
    {
        _totalPricePolicy = totalPricePolicy;
    }

    public Action ViewSale(Guid id)
    {
        return Session.Query<Sale>()
            .Where(x => x.Id == id)
            .Select(x => new SaleView(_totalPricePolicy)
            {
                Id = x.Id,
                Tax = x.Tax
            });
    }
}
于 2013-07-07T09:01:14.900 回答