将存储库注入ASP.NET控制器的最佳方法是什么?

时间:2013-08-14 08:37:22

标签: asp.net-mvc ninject

我们有一个用ASP.NET MVC编写的项目,我们使用NInject将存储库注入控制器。目前我们正在使用属性和Inject-attribute来注入存储库,这很好用:

[Inject]
public IMyRepository MyRepos {get;set;}

另一种注入方式是使用NInjectServiceLocator

“手动”进行注入
var myRepos = NInjectServiceLocatorInstance.Resolve<IMyRepository>();

现在我想知道以下内容:第一种方法要求所有存储库都列在控制器的顶部(当然不一定在顶部,但它是最合理的位置)。每当发出请求时,NInject都会实例化每个存储库。无论是否在特定Action内实际需要所有存储库,都会发生这种情况。

使用第二种方法,您可以更精确地控制实际需要哪些存储库,因此在创建控制器时可能会节省一些开销。但是您可能还必须包含代码以在多个位置检索相同的存储库。

哪一个更好?是否拥有一堆存储库属性更好还是更好地解决在您需要的时间和地点实际需要特定操作的存储库?注入“无用”存储库是否会导致性能下降?那里有(甚至;-)更好的解决方案吗?

3 个答案:

答案 0 :(得分:3)

我更喜欢构造函数注入:

private readonly IMyRepository _repository;

public MyController(IMyRepository repository)
{
    _repository = repository;
}
  • 所有依赖项都列在一个操作中
  • 您的控制器无需了解有关NInject的任何信息
  • 您可以通过将接口直接存根到构造函数来对没有NInjects参与的控制器进行单元测试
  • Controller具有更清晰的代码

NInject或任何其他DI框架将在幕后完成工作,让您专注于实际问题,而不是DI。

答案 1 :(得分:2)

使用DI时,

Constructor Injection应该是您的默认选择。

你应该问问自己,控制器是否真的依赖于那个特定的类来工作。

如果您只有特定方法需要依赖项,那么Method injection也可能是特定方案的解决方案。

我从未使用Property Injection,但Mark Seeman在他的书(Dependency Injection in .NET)中对此进行了描述:

  

只有当你正在开发的课程有好处时,才应该使用PROPERTY INJECTION   LOCAL DEFAULT,您仍然希望启用调用者以提供不同的实现   班级的依赖性。

     

当DEPENDENCY是可选的时,最好使用PROPERTY INJECTION。

     

注意有关物业注入的问题存在争议   表示可选的依赖性。作为一般的API设计原则,我   将属性视为可选属性,因为您很容易忘记分配   他们和编译器不抱怨。如果你接受这个原则   一般情况下,您还必须在DI的特殊情况下接受它。 4

本地默认值描述为:

  

在同一程序集中定义的ABSTRACTION的默认实现   消费者。

除非您正在构建API,否则我建议不要使用Property Injection

  

每当发出请求时,NInject都会实例化每个存储库。无论是否在特定Action中实际需要所有存储库,都会发生这种情况。

在使用构造函数注入时,我认为你不应该担心性能

答案 2 :(得分:0)

到目前为止,我最喜欢的方法是:

public class MyController : Controller
{
    public IMyRepository MyRepos {get;set;}

    public MyController(IMyRepository repo)
    {
        MyRepos = repo;
    }
}

所以你可以使用NuGet包,比如Ninject.MVC3(或MVC4),它特别支持将Ninject内核包含在MVC自己的IoC类中

https://github.com/ninject/ninject.web.mvc/wiki/MVC3

一旦你有了Ninject钩子,就可以让它将注入实例的工作带到控制器的构造函数中,我认为它更清晰。

编辑:

好的,好的。在更彻底地阅读了你的问题之后,我会看到你的目标。简而言之,如果您想挑选并选择实施哪些仓库类别,那么您需要手动调用,例如:

var myRepos = NInjectServiceLocatorInstance.Resolve<IMyRepository>();

您无法配置Ninject(或任何其他IoC AFAIK)以根据当前执行方法有选择地创建对象实例。这种级别的粒度是我认为的一个真正的边缘情况,这可以通过编写自己的控制器工厂类来解决,但这样就太过分了。