ASP.NET Core Controller与IOC团结问题整理

看到标题大概各人会有所疑问ControllerIOC能有啥拘束,可是我照旧拒绝当一个标题党的。相信有很大一部门人已经知道了这么一个结论,默认环境下ASP.NET CoreController并不会托管到IOC容器中,留意要害字我说的是"默认",首先咱们不先说为什么,假如尚有不知道这个结论的同学们可以本身验证一下,验证方法也很简朴,或许可以通过以下几种方法。

验证Controller不在IOC中

首先,我们可以实验在ServiceProvider中获取某个Controller实例,好比

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { var productController = app.ApplicationServices.GetService<ProductController>(); }

这是最直接的方法,可以在IOC容器中获取注册过的范例实例,很显然功效会为null。另一种方法,也是操作它的另一个特征,那就是通过结构注入的方法,如下所示我们在OrderController中注入ProductController,显然这种方法是不公道的,可是为了求证一个功效,我们这里仅做演示,强烈不发起实际开拓中这么写,这是不类型也是不公道的写法

public class OrderController : Controller { private readonly ProductController _productController; public OrderController(ProductController productController) { _productController = productController; } public IActionResult Index() { return View(); } }

功效显然是会报一个错InvalidOperationException: Unable to resolve service for type 'ProductController' while attempting to activate 'OrderController'。原因就是因为ProductController并不在IOC容器中,所以通过注入的方法会报错。尚有一种方法,大概不太常用,这个是操作注入的一个特征,大概有些同学已经相识过了,那就是通过自带的DI,纵然一个类中包括多个结构函数,它也会选择最优的一个,也就是说自带的DI答允类包括多个结构函数。操作这个特征,我们可以在Controller中验证一下

public class OrderController : Controller { private readonly IOrderService _orderService; private readonly IPersonService _personService; public OrderController(IOrderService orderService) { _orderService = orderService; } public OrderController(IOrderService orderService, IPersonService personService) { _orderService = orderService; _personService = personService; } public IActionResult Index() { return View(); } }

我们在Controller中编写了两个结构函数,理论上来说这是切合DI特征的,运行起来测试一下,依然会报错InvalidOperationException: Multiple constructors accepting all given argument types have been found in type 'OrderController'. There should only be one applicable constructor。以上各种都是为了证实一个结论,默认环境下Controller并不会托管到IOC傍边。

DefaultControllerFactory源码探究

上面固然我们看到了一些现象,能说明Controller默认环境下并不在IOC中托管,可是还没有足够的说服力,接下来我们就来查察源码,这是最有说服力的。我们找到Controller工场注册的处所,在MvcCoreServiceCollectionExtensions扩展类中[]的AddMvcCoreServices要领里

//给IControllerFactory注册默认的Controller工场类DefaultControllerFactory //也是Controller建设的进口 services.TryAddSingleton<IControllerFactory, DefaultControllerFactory>(); //真正建设Controller的事情类DefaultControllerActivator services.TryAddTransient<IControllerActivator, DefaultControllerActivator>();

由此我们可以得出,默认的Controller建设工场类为DefaultControllerFactory,那么我们直接找到源码位置[点击查察源码],
为了利便阅读,精简一下源码如下所示

internal class DefaultControllerFactory : IControllerFactory { //真正建设Controller的事情者 private readonly IControllerActivator _controllerActivator; private readonly IControllerPropertyActivator[] _propertyActivators; public DefaultControllerFactory( IControllerActivator controllerActivator, IEnumerable<IControllerPropertyActivator> propertyActivators) { _controllerActivator = controllerActivator; _propertyActivators = propertyActivators.ToArray(); } /// <summary> /// 建设Controller实例的要领 /// </summary> public object CreateController(ControllerContext context) { //建设Controller实例的详细要领(这是要害要领) var controller = _controllerActivator.Create(context); foreach (var propertyActivator in _propertyActivators) { propertyActivator.Activate(context, controller); } return controller; } /// <summary> /// 释放Controller实例的要领 /// </summary> public void ReleaseController(ControllerContext context, object controller) { _controllerActivator.Release(context, controller); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdxys.html