加入收藏 | 设为首页 | 会员中心 | 我要投稿 南平站长网 (https://www.0599zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

深入探究ASP.NET Core Startup初始化问题

发布时间:2020-12-10 15:38:47 所属栏目:Asp教程 来源:网络整理
导读:副标题#e# Startup类相信大家都比较熟悉,在我们使用ASP.NET Core开发过程中经常用到的类,我们通常使用它进行IOC服务注册,配置中间件信息等。虽然它不是必须的,但是将这些操作统一在Startup中做处理,会在实际开发中带来许多方便。当我们谈起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为何会被调用

(编辑:南平站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读