可以在控制器中使用 IKernel 吗?
Is it ok to use IKernel in Controllers?
我有一个包含许多不同 Action 的 MVC 控制器。我使用 Ninject
进行依赖注入。
每个操作都需要一些特定的依赖项。
如何更好地注入这些依赖项?
将它们全部注入到Controller中,并使用我需要的。
只在Controller中注入IKernel
,获取当前执行的action中的依赖
我认为方法 #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();
}
}
您所描述的是使用 Ninject
的 IKernel
作为服务定位器,Mark Seemann 定义的是一种反模式 (source)
Service Locator is a well-known pattern, and since it was described by Martin Fowler, it must be good, right?
No, it's actually an anti-pattern and should be avoided.
他用细节和例子解释了为什么 Service Locator
是反模式,例如
- API usage issues
- Maintenance issues
您还可以查看 this 问题了解更多信息
如您所知,示例 #2 是 服务定位器模式。我们中的许多人在过去的好日子里都在 ASP.Net Web 表单中使用过它 - 那时我们还不知道更好。
但是,ASP.Net MVC 存在更好的替代方案,例如构造函数注入 - DI 的默认目标 - 示例 #1。
服务定位器几乎没有问题。其中之一就是不遵循不叫我们,我们就叫你的原则。相反,我们直接索要我们需要的东西,而不是交给我们。
使用服务定位器,我们必须检查代码,搜索用于检索所需服务的反复无常的调用。构造函数注入允许我们查看
通过 IntelliSense 查看构造函数或在远处查看所有依赖项。
来源:Dependency Injection in .NET by Mark Seemann and Adaptive Code via C# by Gary McLean Hall
我有一个包含许多不同 Action 的 MVC 控制器。我使用 Ninject
进行依赖注入。
每个操作都需要一些特定的依赖项。
如何更好地注入这些依赖项?
将它们全部注入到Controller中,并使用我需要的。
只在Controller中注入
IKernel
,获取当前执行的action中的依赖
我认为方法 #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();
}
}
您所描述的是使用 Ninject
的 IKernel
作为服务定位器,Mark Seemann 定义的是一种反模式 (source)
Service Locator is a well-known pattern, and since it was described by Martin Fowler, it must be good, right?
No, it's actually an anti-pattern and should be avoided.
他用细节和例子解释了为什么 Service Locator
是反模式,例如
- API usage issues
- Maintenance issues
您还可以查看 this 问题了解更多信息
如您所知,示例 #2 是 服务定位器模式。我们中的许多人在过去的好日子里都在 ASP.Net Web 表单中使用过它 - 那时我们还不知道更好。
但是,ASP.Net MVC 存在更好的替代方案,例如构造函数注入 - DI 的默认目标 - 示例 #1。
服务定位器几乎没有问题。其中之一就是不遵循不叫我们,我们就叫你的原则。相反,我们直接索要我们需要的东西,而不是交给我们。
使用服务定位器,我们必须检查代码,搜索用于检索所需服务的反复无常的调用。构造函数注入允许我们查看 通过 IntelliSense 查看构造函数或在远处查看所有依赖项。
来源:Dependency Injection in .NET by Mark Seemann and Adaptive Code via C# by Gary McLean Hall