在控制器中使用IKernel可以吗?

时间:2017-03-13 21:01:23

标签: asp.net-mvc dependency-injection ninject

我有一个MVC控制器,有很多不同的动作。我使用Ninject进行依赖注入。

每个操作都需要一些特定的依赖项。

如何更好地注入这些依赖项?

  1. 在Controller中注入所有这些内容,然后使用我需要的内容。

  2. 仅在Controller中注入IKernel,并在当前执行的操作中获取依赖项。

  3. 我认为方法#2更好,因为我可以避免创建一些不会被使用的依赖项。

    示例1:

    public class MyController : Controller
    {
        private readonly IService1 _service1;
        private readonly IService2 _service2;
        private readonly IService3 _service3;
        public MyController(IService1 service1, IService2 service2, IService3 service3)
        {
            _service1 = service1;
            _service2 = service2;
            _service3 = service3;
        }
    
        public ActionResult Action1()
        {
            _service1.Get();
            return View();
        }
    
        public ActionResult Action2()
        {
            _service2.Get();
            return View();
        }
    
        public ActionResult Action3()
        {
            _service3.Get();
            return View();
        }
    }
    

    示例2:

    public class MyController : Controller
    {
        private readonly IKernel _kernel;
        public MyController(IKernel kernel)
        {
            _kernel = kernel;
        }
    
        public ActionResult Action1()
        {
            IService1 _service1 = _kernel.Get<IService1>();
            _service1.Get();
    
            return View();
        }
    
        public ActionResult Action2()
        {
            IService2 _service2 = _kernel.Get<IService2>();
            _service2.Get();
    
            return View();
        }
    
        public ActionResult Action3()
        {
            IService3 _service3 = _kernel.Get<IService3>();
            _service3.Get();
    
            return View();
        }
    }
    

2 个答案:

答案 0 :(得分:3)

如您所知,示例#2是 服务定位器模式 。我们中的许多人在过去的好日子里在ASP.Net Web Form中使用它 - 当时我们还不知道更好。

然而,ASP.Net MVC存在更好的替代方案,例如构造函数注入 - DI的默认目标 - 示例#1。

服务定位器几乎没有问题。其中一个是它不遵循 不要打电话给我们,我们会叫你 原则。相反,我们直接询问我们需要的东西,而不是把它们交给我们。

使用服务定位器,我们必须检查代码,搜索检索所需服务的反复无常的调用。构造函数注入允许我们查看 依赖关系 - 所有这些 - 通过智能感知一瞥构造函数或远距离。

来源:Dependency Injection in .NET by Mark SeemannAdaptive Code via C# by Gary McLean Hall

答案 1 :(得分:1)

您所描述的是使用Ninject的{​​{1}}作为服务定位器,Mark Seemann定义的是一种反模式(source

  

服务定位器是一个众所周知的模式,因为它由Martin Fowler描述,它一定很好,对吗?

     

不,它实际上是反模式,应该避免。

他解释了为什么IKernel是反模式的细节和例子,例如

  
      
  • API使用问题
  •   
  • 维护问题
  •   

您还可以查看this问题以获取更多信息