Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 在控制器中使用IKernel可以吗?_Asp.net Mvc_Dependency Injection_Ninject - Fatal编程技术网

Asp.net mvc 在控制器中使用IKernel可以吗?

Asp.net mvc 在控制器中使用IKernel可以吗?,asp.net-mvc,dependency-injection,ninject,Asp.net Mvc,Dependency Injection,Ninject,我有一个具有许多不同操作的MVC控制器。我使用Ninject进行依赖注入 每个操作都需要一些特定的依赖项 如何更好地注入这些依赖关系 将它们全部注入控制器,并使用我需要的 仅在控制器中注入IKernel,并在当前执行的操作中获取依赖项 我认为这种方法#2更好,因为我可以避免创建一些不会使用的依赖项 例1: public class MyController : Controller { private readonly IService1 _service1; private r

我有一个具有许多不同操作的MVC控制器。我使用
Ninject
进行依赖注入

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

如何更好地注入这些依赖关系

  • 将它们全部注入控制器,并使用我需要的

  • 仅在控制器中注入
    IKernel
    ,并在当前执行的操作中获取依赖项

  • 我认为这种方法#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();
        }
    }
    
    公共类MyController:Controller
    {
    私有只读IKernel_内核;
    公共MyController(IKernel内核)
    {
    _内核=内核;
    }
    公共行动结果行动1()
    {
    IService1 _service1=_kernel.Get();
    _service1.Get();
    返回视图();
    }
    公共行动结果行动2()
    {
    IService2_service2=_kernel.Get();
    _service2.Get();
    返回视图();
    }
    公共行动结果行动3()
    {
    IService3\u service3=\u kernel.Get();
    _service3.Get();
    返回视图();
    }
    }
    
    您所描述的是使用
    Ninject
    IKernel
    作为服务定位器,Mark Seemann将其定义为反模式()

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

    不,这实际上是一种反模式,应该避免

    他用细节和例子解释了为什么
    服务定位器
    是一种反家长行为,例如

    • API使用问题
    • 维修问题


    您还可以查看更多信息的问题

    ,如您所知,示例2是服务定位器模式。在过去的好日子里,我们中的许多人都在ASP.NETWeb表单中使用它——那时我们还不知道有什么更好的方法

    然而,ASP.NETMVC有更好的替代方案,比如构造函数注入——DI示例1的默认目标

    服务定位器几乎没有问题。其中之一是它不符合原则,不要打电话给我们,我们会打电话给你。相反,我们直接要求得到我们需要的东西,而不是把它们交给我们

    使用服务定位器,我们必须检查代码,搜索检索所需服务的反复无常的调用。构造函数注入允许我们查看 依赖关系—通过IntelliSense,只需看一眼构造器,或者看一眼远处的构造器


    资料来源:和

    。切勿将容器注射到任何地方,除非。这意味着控制器是不可能的。当然,用这种方式制作控制器可能更容易,但当你需要弄清楚控制器依赖于什么时,你付出的维护代价远远不止这些。我知道使用服务定位器是不好的,特别是因为你可能会被诱惑只发送服务定位器作为你所有服务的依赖项。我能想到的唯一例外是在应用程序入口点,在这种情况下,只有控制器控制器不在应用程序入口点。控制器位于UI层中,该层与应用程序的入口点不同。关于这一点,您可以找到更全面的解释。请注意,如果您的控制器有一大组依赖项,其中每个操作都有自己的一组不被其他操作使用的依赖项,这意味着控制器中的方法具有较低的内聚性,这表明违反了单一责任原则。在这种情况下,最好将控制器拆分为多个较小的控制器。