.net core mvc启动顺序以及主要部件2
程序员文章站
2023-08-12 10:09:23
前一篇提到WebHost.CreateDefaultBuilder(args)方法创建了WebHostBuilder实例,WebHostBuilder实例有三个主要功能 1、构建了IConfiguration实例和基础环境配置,2、构建了IServiceCollection服务,也就是依赖注入的容器 ......
前一篇提到webhost.createdefaultbuilder(args)方法创建了webhostbuilder实例,webhostbuilder实例有三个主要功能 1、构建了iconfiguration实例和基础环境配置,2、构建了iservicecollection服务,也就是依赖注入的容器,3、创建了webhost实例,这个webhost就是我们的接收请求的第一个管道,其中暴露出来的主要方法build,请看源代码:
1 public iwebhost build() 2 { 3 if (!_webhostbuilt) 4 { 5 _webhostbuilt = true; 6 aggregateexception hostingstartuperrors; 7 iservicecollection servicecollection = buildcommonservices(out hostingstartuperrors); 8 iservicecollection servicecollection2 = servicecollection.clone(); 9 iserviceprovider hostingserviceprovider = _003cbuild_003eg__getproviderfromfactory_007c13_0(servicecollection); 10 if (!_options.suppressstatusmessages) 11 { 12 if (environment.getenvironmentvariable("hosting:environment") != null) 13 { 14 console.writeline("the environment variable 'hosting:environment' is obsolete and has been replaced with 'aspnetcore_environment'"); 15 } 16 if (environment.getenvironmentvariable("aspnet_env") != null) 17 { 18 console.writeline("the environment variable 'aspnet_env' is obsolete and has been replaced with 'aspnetcore_environment'"); 19 } 20 if (environment.getenvironmentvariable("aspnetcore_server.urls") != null) 21 { 22 console.writeline("the environment variable 'aspnetcore_server.urls' is obsolete and has been replaced with 'aspnetcore_urls'"); 23 } 24 } 25 addapplicationservices(servicecollection2, hostingserviceprovider); 26 webhost webhost = new webhost(servicecollection2, hostingserviceprovider, _options, _config, hostingstartuperrors); 27 try 28 { 29 webhost.initialize(); 30 ilogger<webhost> requiredservice = webhost.services.getrequiredservice<ilogger<webhost>>(); 31 foreach (igrouping<string, string> item in from g in _options.getfinalhostingstartupassemblies().groupby((string a) => a, stringcomparer.ordinalignorecase) 32 where g.count() > 1 33 select g) 34 { 35 requiredservice.logwarning($"the assembly {item} was specified multiple times. hosting startup assemblies should only be specified once."); 36 } 37 return webhost; 38 } 39 catch 40 { 41 webhost.dispose(); 42 throw; 43 } 44 } 45 throw new invalidoperationexception(resources.webhostbuilder_singleinstance); 46 }
这个方法中有几个笔记重要的部分,下面我给标记一下
调用buildcommonservices私有方法主要是注入一些程序所需的基础组件,请看源代码:
1 private iservicecollection buildcommonservices(out aggregateexception hostingstartuperrors) 2 { 3 hostingstartuperrors = null; 4 _options = new webhostoptions(_config, assembly.getentryassembly()?.getname().name); 5 if (!_options.preventhostingstartup) 6 { 7 list<exception> list = new list<exception>(); 8 foreach (string item in _options.getfinalhostingstartupassemblies().distinct(stringcomparer.ordinalignorecase)) 9 { 10 try 11 { 12 foreach (hostingstartupattribute customattribute in assembly.load(new assemblyname(item)).getcustomattributes<hostingstartupattribute>()) 13 { 14 ((ihostingstartup)activator.createinstance(customattribute.hostingstartuptype)).configure(this); 15 } 16 } 17 catch (exception innerexception) 18 { 19 list.add(new invalidoperationexception("startup assembly " + item + " failed to execute. see the inner exception for more details.", innerexception)); 20 } 21 } 22 if (list.count > 0) 23 { 24 hostingstartuperrors = new aggregateexception(list); 25 } 26 } 27 string contentrootpath = resolvecontentrootpath(_options.contentrootpath, appcontext.basedirectory); 28 _hostingenvironment.initialize(contentrootpath, _options); 29 _context.hostingenvironment = _hostingenvironment; 30 servicecollection servicecollection = new servicecollection(); 31 servicecollection.addsingleton(_options); 32 ((iservicecollection)servicecollection).addsingleton((ihostingenvironment)_hostingenvironment); 33 ((iservicecollection)servicecollection).addsingleton((microsoft.extensions.hosting.ihostingenvironment)_hostingenvironment); 34 servicecollection.addsingleton(_context); 35 iconfigurationbuilder configurationbuilder = new configurationbuilder().setbasepath(_hostingenvironment.contentrootpath).addconfiguration(_config); 36 foreach (action<webhostbuildercontext, iconfigurationbuilder> configureappconfigurationbuilderdelegate in _configureappconfigurationbuilderdelegates) 37 { 38 configureappconfigurationbuilderdelegate(_context, configurationbuilder); 39 } 40 iconfigurationroot configurationroot = configurationbuilder.build(); 41 ((iservicecollection)servicecollection).addsingleton((iconfiguration)configurationroot); 42 _context.configuration = configurationroot; 43 diagnosticlistener implementationinstance = new diagnosticlistener("microsoft.aspnetcore"); 44 servicecollection.addsingleton(implementationinstance); 45 ((iservicecollection)servicecollection).addsingleton((diagnosticsource)implementationinstance); 46 servicecollection.addtransient<iapplicationbuilderfactory, applicationbuilderfactory>(); 47 servicecollection.addtransient<ihttpcontextfactory, httpcontextfactory>(); 48 servicecollection.addscoped<imiddlewarefactory, middlewarefactory>(); 49 servicecollection.addoptions(); 50 servicecollection.addlogging(); 51 servicecollection.addtransient<istartupfilter, autorequestservicesstartupfilter>(); 52 servicecollection.addtransient<iserviceproviderfactory<iservicecollection>, defaultserviceproviderfactory>(); 53 servicecollection.addsingleton<objectpoolprovider, defaultobjectpoolprovider>(); 54 if (!string.isnullorempty(_options.startupassembly)) 55 { 56 try 57 { 58 type startuptype = startuploader.findstartuptype(_options.startupassembly, _hostingenvironment.environmentname); 59 if (introspectionextensions.gettypeinfo(typeof(istartup)).isassignablefrom(startuptype.gettypeinfo())) 60 { 61 servicecollection.addsingleton(typeof(istartup), startuptype); 62 } 63 else 64 { 65 servicecollection.addsingleton(typeof(istartup), delegate (iserviceprovider sp) 66 { 67 ihostingenvironment requiredservice = sp.getrequiredservice<ihostingenvironment>(); 68 return new conventionbasedstartup(startuploader.loadmethods(sp, startuptype, requiredservice.environmentname)); 69 }); 70 } 71 } 72 catch (exception source) 73 { 74 exceptiondispatchinfo capture = exceptiondispatchinfo.capture(source); 75 ((iservicecollection)servicecollection).addsingleton((func<iserviceprovider, istartup>)delegate 76 { 77 capture.throw(); 78 return null; 79 }); 80 } 81 } 82 foreach (action<webhostbuildercontext, iservicecollection> configureservicesdelegate in _configureservicesdelegates) 83 { 84 configureservicesdelegate(_context, servicecollection); 85 } 86 return servicecollection; 87 }
这个方法中其中就包含了注入iconfiguration的代码和构建iservicecollection容器的代码,当然还有一些其他的主要中间件注入啊iapplicationbuilderfactory,包括httpcontextfactory等等都在这个方法里面被iservicecollection容器管理,具体请看下图
这里讲清楚之后,我们直接进入usestartup方法中,这个方法是注入了startup的实例,请看主要源代码
1 public static iwebhostbuilder usestartup(this iwebhostbuilder hostbuilder, type startuptype) 2 { 3 string name = startuptype.gettypeinfo().assembly.getname().name; 4 return hostbuilder.usesetting(webhostdefaults.applicationkey, name).configureservices(delegate (iservicecollection services) 5 { 6 if (introspectionextensions.gettypeinfo(typeof(istartup)).isassignablefrom(startuptype.gettypeinfo())) 7 { 8 services.addsingleton(typeof(istartup), startuptype); 9 } 10 else 11 { 12 services.addsingleton(typeof(istartup), delegate (iserviceprovider sp) 13 { 14 ihostingenvironment requiredservice = sp.getrequiredservice<ihostingenvironment>(); 15 return new conventionbasedstartup(startuploader.loadmethods(sp, startuptype, requiredservice.environmentname)); 16 }); 17 } 18 }); 19 }
上面只是被iservicecollection所管理 并没有真正起作用,真正调用的是main方法中的build().run(),这里的build就是上面那个iwebhostbuilder中的主要的构建方法,而run则是正式启动应用程序和调用startup中的configureservices方法
请看代码:
分享program类的过程大致就到这里了