3

因此,在使用 MVC(或 Web API)的 Repository 模式的所有 DI 示例中,有 99% 在控制器操作中显示了与下面类似的内容(省略了构造函数注入代码_repository)。问题是假设不需要首先处理任何内容(如规则)并且立即开始持久性:

public ActionResult Create(Person person)
{
    if (ModelState.IsValid)
    {
      _repository.Add(person);
    }

    return View(person);
}

问题是,如果我需要在持久化对象之前处理领域层中的规则怎么办?person显然,我不在 Controller 中执行该逻辑,而是在域层中需要它。下面哪个选项更好:

选项 1:将要在域/业务层中调用的存储库上的所有持久性细节委托并从控制器中拉出。更新后的代码如下所示:

if (ModelState.IsValid)
{
  using (busniessLogic = new MyApp.BusniessLogic(_repository))
  {
       busniessLogic.ProcessRulesAndSavePerson(person);
  }
}

领域层可能有这样的方法:

public void ProcessRulesAndSavePerson(Person person)
{
   //process some rules...

   if(rules = true)
   {
     //use injected repository to add now that rules have passed
     _repository.Add(person)
   }
}

选项 2:在 Controller 中保持与现在相同,但只需在保存到存储库之前调用处理规则即可。更新后的代码如下:

if (ModelState.IsValid)
{
  using (busniessLogic = new MyApp.BusniessLogic())
  {           
       busniessLogic.ProcessRulesAboutPerson(person);
       _repository.Add(person)
  }
}

我也对其他想法持开放态度,但我倾向于选项 #1。我喜欢保持控制器薄,只是将注入的 _repository 传递给需要它的层。

对此的任何帮助表示赞赏,谢谢!

4

2 回答 2

4

这两个选项都将创建对业务逻辑处理器的依赖,在使用关键字时始终必须小心,new因为当您尝试对方法进行单元测试时,几乎总是会遇到问题,这违背了依赖注入的目的。

您最好创建一个处理复杂业务逻辑的服务并将其注入您的控制器。如果您的大部分逻辑都很复杂,我会跳过将存储库一起传递给控制器​​,而只依赖服务为我处理所有事情。

控制器:

public MyController(IPersonService personService) 
{
    _personService = personService;
}

public ActionResult Create(Person person)
{
    if (ModelState.IsValid)
       _personService.Create(person);
    else
       ......
}

人员服务:

public PersonService(IPersonRepository repo) 
{
    _repo = repo;
}

public int Create(Person person)
{
    //businesslogic
    return _repo.Add(person);
}
于 2013-01-14T19:26:49.677 回答
3

不一定是最好的方法,但这是我通常的做法:

  • IService(在您的情况下为业务逻辑)被注入控制器(而不是 IRepository)
  • 如果 ModelState 有效 => 控制器将调用 IService 中将模型作为参数的方法
  • 如果需要,将 IRepository 注入到 Service 实例中。

这使我能够: - 能够对提供 IService 模型的控制器进行单元测试。- 让控制器不了解存储库和数据访问层。

于 2013-01-14T19:17:48.127 回答