2

初始警告:很长的帖子,无论如何我可能完全错误地理解了模式:

给定以下类,它是客户聚合的开始:

public class Customer : KeyedObject
{

   public Customer(int customerId)
   {
      _customerRepository.Load(this);
   }

   private ICustomerRepository _customerRepository = IoC.Resolve(..);  
   private ICustomerTypeRepository = _customerTypeRepository = IoC.Resolve(..);

   public virtual string CustomerName {get;set;}
   public virtual int CustomerTypeId [get;set;}

   public virtual string CustomerType
   {
      get
      {
         return _customerTypeRepository.Get(CustomerTypeId);
      }
   }

}

CustomerType 由一个值对象表示:

public class CustomerType : ValueObject
{
   public virtual int CustomerTypeId {get;set;}
   public virtual string Description {get;set;}
}

当我有一个带有 CustomerTypeId 的客户对象时,这一切都很好。但是,当我想在我的 MVC 视图中填充 DropDownList 时,我正在努力解决如何从 ICustomerTypeRepostory 正确获取 CustomerType 值列表的概念。

ICustomerTypeRepository非常简单:

public interface ICustomerTypeRepository
{
   public CustomerType Get(int customerTypeId);
   public IEnumerable<CustomerType> GetList();
}

基本上,我想要的是能够ICustomerTypeRepository从我的控制器正确调用,但是我认为最好将 DAL(存储库)层与控制器分开。现在,我只是把事情复杂化了吗?

这就是我的控制器当前的状态:

public class CustomerController : ControllerBase
{ 

    private ICustomerTypeRepository _customerTypeRepository = IoC.Resolve(..);

    public ActionResult Index()
    {
       Customer customer = new Customer(customerId); 
       IEnumerable<CustomerType> customerTypeList = 
          _customerTypeRepository.GetList();

       CustomerFormModel model = new CustomerFormModel(customer);
       model.AddCustomerTypes(customerTypeList );
    }
}

这对我来说似乎是错误的,因为我在 Controller 和 Customer 中有存储库。对我来说,应该有一个用于 CustomerType 的隔离访问层,这似乎是合乎逻辑的。即CustomerType.GetList()

public class CustomerType : ValueObject
{
   // ... Previous Code

   private static ICustomerTypeRepository _customerTypeRepository = IoC.Resolve(..);

   public static IEnumerable<CustomerType> GetList()
   {
      _customerTypeRepository.GetList();
   }
}

那么,我应该通过哪种方式将CustomerType对象暴露ICustomerTypeRepositoryCustomerController?

4

2 回答 2

2

我认为这里有几点需要考虑。

首先,如果您真的对域建模感兴趣,您将不惜一切代价尝试使域实体本身免于横切关注点,例如验证、IoC 容器和持久性,尽管有 Active Record 模式。

这意味着Customer即使您使用接口和服务定位器,它也不应该有任何对存储库的引用。它应该被设计成从目标客户/用户的角度反映“客户”的属性——或构成——“客户”的属性。

抛开域建模不谈,我有点担心IoC在变量初始化程序中使用您的服务定位器。您将失去任何捕获异常的机会,并且构造函数抛出的异常非常难以调试(这些初始化程序在您的第一个非静态构造函数中的任何代码之前运行)。

使用静态网关/服务定位器代替注入依赖项也使该类几乎无法测试(使用自动化单元测试方法,即 - 您可以进行集成和手动测试,但测试失败不太可能将您指向损坏的位很容易——与单元测试相反,在单元测试中,你确切地知道你正在测试什么,因此什么被破坏了)。

应用程序将更典型地使用存储库来获取实体,而不是让Customer对象通过调用构造函数来填充自己的数据,因此它从完全填充的存储库返回,包括属性。在这种情况下,这似乎可能发生在._customerRepository.Load(this)CustomerTypeCustomerController

您表示您希望从CustomerController所在的层中拥有一个单独的 DAL,并且您实际上拥有它——这就是使用存储库接口的地方。您注入该接口的一些实现(或者在这种情况下,获取IoC 实现的实现),但该存储库的实际实现可以存在于单独的层中(甚至可以是另一个程序集)。这是一种称为分离接口的模式。

就个人而言,我会将 CustomerController 重构为如下所示:

public class CustomerController : ControllerBase
{ 
     private ICustomerTypeRepository _customerTypeRepository;
     private ICustomerRepository _customerRepository;

     public CustomerController(ICustomerRepository customerRepository,
        ICustomerTypeRepository customerTypeRepository)
     {
        _customerRepository = customerRepository;
        _customerTypeRepository = customerTypeRepository;
     }

     public ActionResult Index()
     {
         Customer customer 
             = _customerRepository.GetCustomerWithId(customerId); 
             // from where does customerId come?

         IEnumerable<CustomerType> customerTypeList 
             = _customerTypeRepository.GetTypes();

        . . .

     }
}

…并且我会从Customer任何其他域实体类中获取对存储库的所有引用。

于 2010-07-09T02:37:29.810 回答
0

如何更改您的客户域模型以包含 CustomerTypes 的属性?这也将不再需要在每次调用 CustomerType 时访问存储库。

public class Customer : KeyedObject
{

   public Customer(int customerId)
   {
      _customerRepository.Load(this);

      ICustomerTypeRepository _customerTypeRepository = IoC.Resolve(..);
      _customerTypes = _customerTypeRepository.GetList();
   }

   private ICustomerRepository _customerRepository = IoC.Resolve(..);  

   public virtual string CustomerName {get;set;}
   public virtual int CustomerTypeId {get;set;}

   public virtual string CustomerType
   {
      get
      {
         return _customerTypes.Find(CustomerTypeId);
      }
   }

   private IEnumerable<CustomerType> _customerTypes;
   public virtual IEnumerable<CustomerType> CustomerTypes
   {
      get
      {
          return _customerTypes
      }
   }
}
于 2010-07-06T02:32:34.113 回答