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

services.AddMvc().AddControllersAsServices(); //或其他方法,这取决于你构建的Web项目标用途可以是WebApi、Mvc、RazorPage等 //services.AddMvcCore().AddControllersAsServices();

相信各人都看到了,玄机就在AddControllersAsServices要领中,可是它存在于MvcCoreMvcBuilderExtensions类和MvcCoreMvcCoreBuilderExtensions类中,不外问题不大,因为它们的代码是完全一样的。只是因为你可以通过多种方法构建Web项目好比AddMvc可能AddMvcCore,空话不多说直接上代码[]

public static IMvcBuilder AddControllersAsServices(this IMvcBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var feature = new ControllerFeature(); builder.PartManager.PopulateFeature(feature); //第一将Controller实例添加到IOC容器中 foreach (var controller in feature.Controllers.Select(c => c.AsType())) { //注册的声明周期是Transient builder.Services.TryAddTransient(controller, controller); } //第二替换掉原本DefaultControllerActivator的为ServiceBasedControllerActivator builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); return builder; }

第一点没问题那就是将Controller实例添加到IOC容器中,第二点它替换掉了DefaultControllerActivator为为ServiceBasedControllerActivator。通过上面我们报告的源码相识到DefaultControllerActivator是默认提供Controller实例的处所是获取Controller实例的焦点地址,那么我们看看ServiceBasedControllerActivator与DefaultControllerActivator到底有何差异,直接贴出代码[点击查察源码]

public class ServiceBasedControllerActivator : IControllerActivator { public object Create(ControllerContext actionContext) { if (actionContext == null) { throw new ArgumentNullException(nameof(actionContext)); } //获取Controller范例 var controllerType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType(); //通过Controller范例在容器中获取实例 return actionContext.HttpContext.RequestServices.GetRequiredService(controllerType); } public virtual void Release(ControllerContext context, object controller) { } }

相信各人对上面的代码一目了然了,和我们上面描写的一样,将建设Controller实例的处所改革了在容器中获取的方法。不知道各人有没有留意到ServiceBasedControllerActivator的Release的要领居然没有实现,这并不是我没有粘贴出来,确实是没有代码,之前我们看到的DefaultControllerActivator但是有挪用Controller的Disposed的要领,这里却啥也没有。相信智慧的你已经想到了,因为Controller已经托管到了IOC容器中,所以他的生命及其相关释放都是由IOC容器完成的,所以这里不需要任何操纵。

我们上面还看到了注册Controller实例的时候利用的是TryAddTransient要领,也就是说每次城市建设Controller实例,至于为什么,我想或许是因为每次请求都其实只会需要一个Controller实例,何况EFCore的注册方法官方发起也是Scope的,而这里的Scope正是对应的一次Controller请求。在加上自带的IOC会晋升依赖范例的声明周期,假如将Controller注册为单例的话假如利用了EFCore那么它也会被晋升为单例,这样会存在很大的问题。也许正是基于这个原因默认才将Controller注册为Transient范例的,虽然这并不代表只能注册为Transient范例的,假如你不利用雷同EFCore这种需要浸染域为Scope的处事的时候,并且担保利用的主键都可以利用单例的话,完全可以将Controller注册为此外生命周期,虽然这种方法小我私家不是很发起。

Controller团结Autofac

有时候各人大概会团结Autofac一起利用,Autofac确实是一款很是优秀的IOC框架,它它支持属性和结构两种方法注入,关于Autofac托管自带IOC的道理咱们在之前的文章浅谈.Net Core DependencyInjection源码探究中曾具体的讲授过,这里咱们就不外多的描写了,咱们本日要说的是Autofac和Controller的团结。假如你想保持和原有的IOC一致的利用习惯,即只利用结构注入的话,你只需要完成两步即可

首先将默认的IOC容器替换为Autofac,详细操纵也很是简朴,如下所示

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) //只需要在这里配置ServiceProviderFactory为AutofacServiceProviderFactory即可 .UseServiceProviderFactory(new AutofacServiceProviderFactory());

然后就是咱们之前说的,要将Controller放入容器中,然后修改出产Controller实例的ControllerFactory的操纵为在容器中获取,虽然这一步微软已经为我们封装了便捷的要领

services.AddMvc().AddControllersAsServices();

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

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