Nhibernate 使用ViewModels而不是实体时的DRY策略

Nhibernate 使用ViewModels而不是实体时的DRY策略,nhibernate,domain-driven-design,Nhibernate,Domain Driven Design,我们的许多页面使用定制视图模型,这些模型本质上是NHibernate映射实体的缩减版本 当您拥有一组全局的实体时,重用以实体为中心的业务逻辑的小块是很简单的,因为可以将逻辑添加到实体中。然而,一旦我们有了视图特定的视图模型,这就变得更加困难了 下面是一个人为的例子: // Entity public class Sale : Entity { public Guid Id { get; set; } public decimal Tax { get; set; } pub

我们的许多页面使用定制视图模型,这些模型本质上是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
                });
    }
}
//实体
公共类销售:实体
{
公共Guid Id{get;set;}
公共十进制税{get;set;}
公共价格{get;set;}
公共总价格
{
获取{return Tax+SalePrice;}
}
…更多属性。。。
}
//视图模型
公共类SaleView
{
公共Guid Id{get;set;}
公共十进制税{get;set;}
公共价格{get;set;}
}
公共类控制器
{
公共操作ViewSale(Guid id)
{
返回会话。查询()
.其中(x=>x.Id==Id)
.选择(x=>new SaleView
{
Id=x.Id,
税=x.税,
SalePrice=x.SalePrice
});
}
}
在本例中,您使用什么策略重用实体中当前执行的“TotalPrice”计算


您可以在某个地方将“TotalPrice”作为一个静态方法,并让它接受税收和销售价格作为参数,但这可能会导致相当难看、僵化的代码,特别是随着房地产数量和房地产之间关系的增长。您可以创建一个单独的“TotalPriceCalculator”类,但要处理ViewModel,它需要接受实体和视图模型都实现的接口。这将导致重复代码的激增,因为我们现在必须将每个属性写三次。还可以做些什么?

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

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
            });
    }
}
公共接口策略
{
十进制总价(十进制税、十进制售价);
}
公共类TotalPricePolicy:ITotalPricePolicy
{
公共十进制总价(十进制税、十进制售价)
{
退货税+销售价格;
}
}
公共类销售:实体
{
公共Guid Id{get;set;}
公共十进制税{get;set;}
公共价格{get;set;}
公共十进制总价(ITotalPricePolicy totalPricePolicy)
{
返回totalPricePolicy.TotalPrice(税、售价);
}
}
公共类模型
{
私有只读ITotalPricePolicy _totalPricePolicy;
public SaleViewModel(ITotalPricePolicy totalPricePolicy)
{
_totalPricePolicy=totalPricePolicy;
}
公共Guid Id{get;set;}
公共十进制税{get;set;}
市价
{
获取{return_totalPricePolicy.TotalPrice(Tax,SalePrice);}
}
}
公共类HomeController:控制器
{
私有只读ITotalPricePolicy _totalPricePolicy;
公共家庭控制器(ITotalPricePolicy totalPricePolicy)
{
_totalPricePolicy=totalPricePolicy;
}
公共操作ViewSale(Guid id)
{
返回会话。查询()
.其中(x=>x.Id==Id)
.选择(x=>new SaleView(_totalPricePolicy)
{
Id=x.Id,
税=x.税
});
}
}

+1,这是一种称为策略或策略模式的已知模式。你可以在网站上看到更多