深入探究ASP.NET Core Startup初始化问题
//和ConfigureServices查找方法相同转达Startup实例和情形变量 ConfigureBuilder configureBuilder = StartupLoader.FindConfigureDelegate(startupType, context.HostingEnvironment.EnvironmentName); services.Configure<GenericWebHostServiceOptions>(options => { //通过查察GenericWebHostServiceOptions的源码可知app着实就是IApplicationBuilder实例 options.ConfigureApplication = app => { startupError?.Throw(); //执行Startup.Configure,instance为Startup实例 if (instance != null && configureBuilder != null) { //执行Configure要领转达Startup实例和IApplicationBuilder实例 configureBuilder.Build(instance)(app); } }; }); 我们通过查察GenericWebHostServiceOptions的源码可知ConfigureApplication属性的范例为Action也就是说app参数着实就是IApplicationBuilder接口的实例。通过上面这段代码可以看出,首要逻辑就是挪用StartupLoader的FindConfigureDelegate要领,然后返回ConfigureBuilder制作类,然后构建出Configure要领并执行。起首我们来查察FindConfigureDelegate的逻辑实现 internal static ConfigureBuilder FindConfigureDelegate(Type startupType, string environmentName) { //通过startup范例和要领名为Configure或Configure+情形变量名称的要领 var configureMethod = FindMethod(startupType, "Configure{0}", environmentName, typeof(void), required: true); //用查找到的要领去初始化ConfigureBuilder return new ConfigureBuilder(configureMethod); } 从这里我们可以看到FindConfigureDelegate要领也是挪用的FindMethod要领,只是转达的要领名字符串为Configure或Configure+情形变量,关于FindMethod的要领实现我们在上面讲授ConfigureServices要领的时辰已经很是具体的说过了,这里就不外多的讲授了。总之是通过FindMethod去查找名为Configure的要领或名为Configure+情形变量的要领好比ConfigureDevelopment查找法则和ConfigureServices是完全同等的。可是Configure要领却可以通过参数注入注册到IServiceCollection中的处事,谜底我们同样要在ConfigureBuilder类中去探寻 internal class ConfigureBuilder { //结构函数转达Configure的MethodInfo public ConfigureBuilder(MethodInfo configure) { MethodInfo = configure; } public MethodInfo MethodInfo { get; } //Build要领返回Action<IApplicationBuilder>委托 public Action<IApplicationBuilder> Build(object instance) => builder => Invoke(instance, builder); //执行逻辑 private void Invoke(object instance, IApplicationBuilder builder) { //通过IApplicationBuilder的ApplicationServices获取IServiceProvider实例建设一个浸染域 using (var scope = builder.ApplicationServices.CreateScope()) { //获取IServiceProvider实例 var serviceProvider = scope.ServiceProvider; //获取Configure的全部参数 var parameterInfos = MethodInfo.GetParameters(); var parameters = new object[parameterInfos.Length]; for (var index = 0; index < parameterInfos.Length; index++) { var parameterInfo = parameterInfos[index]; //假如要领参数为IApplicationBuilder范例则直接将转达过来的IApplicationBuilder赋值给它 if (parameterInfo.ParameterType == typeof(IApplicationBuilder)) { parameters[index] = builder; } else { try { //按照要领的参数范例在serviceProvider中获取详细实例赋值给对应参数 parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType); } catch (Exception ex) { //假如对应的要领参数名称,没在serviceProvider中获取到则直接抛出非常 //变相的声名白Configure要领的参数必需是注册在IServiceCollection中的 } } } MethodInfo.InvokeWithoutWrappingExceptions(instance, parameters); } } } 通过ConfigureBuilder类的实现逻辑,可以清楚的看到为何Configure要领参数可以注入任安在IServiceCollection中注册的处事了。接下来我们总结一下Configure要领的初始化逻辑,起首在Startup中查找要领名为Configure或Configure+情形变量名称(好比ConfigureDevelopment)的要领,然后查找IApplicationBuilder范例的参数,假如找到则将措施中的IApplicationBuilder实例转达给它。至于为何Configure要领可以或许通过参数注入任安在IServiceCollection中注册的处事,则是由于轮回Configure中的全部参数然后在IOC容器中获取对应实例赋值过来,Configure要领的参数必然得是在IServiceCollection注册过的范例,不然会抛出非常。 ConfigureContainer为何会被挪用 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |