加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_阳江站长网 (https://www.0662zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 政策 > 正文

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

发布时间:2020-12-11 22:21:37 所属栏目:政策 来源:做站长
导读:这篇文章主要介绍了深入探究ASP.NET Core Startup初始化问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 前言 Startup类相信大家都比较熟悉,在我们使用ASP.NET Core开发过程中经常用到的类,我们通常使用

如果你在ASP.NET Core 3.1中使用过Autofac那么你对ConfigureContainer方法一定不陌生,它和ConfigureServices、Configure方法一样的神奇,在几乎没有任何约束的情况下我们只需要定义ConfigureContainer方法并为方法传递一个ContainerBuilder参数,那么这个方法就能顺利的被调用了。这一切究竟是如何实现的呢,接下来我们继续探究源码,找到了如下的逻辑

[点击查看源码]

//根据规则查找最终返回ConfigureContainerBuilder实例
var configureContainerBuilder = StartupLoader.FindConfigureContainerDelegate(startupType, context.HostingEnvironment.EnvironmentName);
if (configureContainerBuilder.MethodInfo != null)
{
//获取容器类型比如如果是autofac则类型为ContainerBuilder
var containerType = configureContainerBuilder.GetContainerType();
// 存储configureContainerBuilder实例
_builder.Properties[typeof(ConfigureContainerBuilder)] = configureContainerBuilder;
//构建一个Action<HostBuilderContext,containerType>类型的委托
var actionType = typeof(Action<,>).MakeGenericType(typeof(HostBuilderContext), containerType);

// 获取此类型的私有ConfigureContainer方法,然后声明该方法的泛型为容器类型,然后创建这个方法的委托
var configureCallback = GetType().GetMethod(nameof(ConfigureContainer), BindingFlags.NonPublic | BindingFlags.Instance)
.MakeGenericMethod(containerType)
.CreateDelegate(actionType, this);

// 等同于执行_builder.ConfigureContainer<T>(ConfigureContainer),其中T为容器类型。
//C onfigureContainer表示一个委托,即我们在Startup中定义的ConfigureContainer委托
typeof(IHostBuilder).GetMethods().First(m => m.Name == nameof(IHostBuilder.ConfigureContainer))
.MakeGenericMethod(containerType)
.InvokeWithoutWrappingExceptions(_builder, new object[] { configureCallback });
}

继续使用老配方,我们查看StartupLoader的FindConfigureContainerDelegate方法实现

[点击查看源码]

internal static ConfigureContainerBuilder FindConfigureContainerDelegate(Type startupType, string environmentName)
{
//根据startupType和根据environmentName构建的Configure{0}Services字符串先去查找返回类型为IServiceProvider的方法
var configureMethod = FindMethod(startupType, “Configure{0}Container”, environmentName, typeof(void), required: false);
//用查找到的方法去初始化ConfigureContainerBuilder
return new ConfigureContainerBuilder(configureMethod);
}

果然还是这个配方这个味道,废话不多说直接查看ConfigureContainerBuilder源码

[点击查看源码]

internal class ConfigureContainerBuilder
{
public ConfigureContainerBuilder(MethodInfo configureContainerMethod)
{
MethodInfo = configureContainerMethod;
}
public MethodInfo MethodInfo { get; }
public Func<Action<object>, Action<object>> ConfigureContainerFilters { get; set; } = f => f;
public Action<object> Build(object instance) => container => Invoke(instance, container);
//查找容器类型,其实就是ConfigureContainer方法的的唯一参数
public Type GetContainerType()
{
var parameters = MethodInfo.GetParameters();
//ConfigureContainer方法只能包含一个参数
if (parameters.Length != 1)
{
throw new InvalidOperationException($”The {MethodInfo.Name} method must take only one parameter.”);
}
return parameters[0].ParameterType;
}

private void Invoke(object instance, object container)
{
ConfigureContainerFilters(StartupConfigureContainer)(container);
void StartupConfigureContainer(object containerBuilder) => InvokeCore(instance, containerBuilder);
}

//根据传递的container对象执行ConfigureContainer方法逻辑比如使用autofac时ConfigureContainer(ContainerBuilder)
private void InvokeCore(object instance, object container)
{
if (MethodInfo == null)
{
return;
}
var arguments = new object[1] { container };
MethodInfo.InvokeWithoutWrappingExceptions(instance, arguments);
}
}

果不其然千年老方下来还是那个味道,和ConfigureServices、Configure方法思路几乎一致。这里需要注意的是GetContainerType获取的容器类型是ConfigureContainer方法的唯一参数即容器类型,如果传递多个参数则直接抛出异常。其实Startup的ConfigureContainer方法经过花里胡哨的一番操作之后,最终还是转换成了雷士如下的操作方式,这个我们在上面代码中构建actionType的时候就可以看出,最终通过查找到的容器类型去完成注册等相关操作,这里就不过多的讲解了

Host.CreateDefaultBuilder(args)
.ConfigureContainer<ContainerBuilder>((context,container)=> {
container.RegisterType<PersonService>().As<IPersonService>().InstancePerLifetimeScope();
});

总结

本篇文章我们主要是围绕着Startup是如何被初始化进行讲解的,分别讲解了Startup是如何被实例化的,为何Startup的构造函数只能传递IWebHostEnvironment、IHostEnvironment、IConfiguration类型的参数,以及ConfigureServices、Configure、ConfigureContainer方法是如何查找到并被初始化调用的。其中虽然涉及到的代码比较多,但是整体思路在阅读源码后还是比较清晰的。由于笔者文笔有限,可能许多地方描述的不够清晰,亦或是本人能力有限理解的不够透彻,不过本人在文章中都标记了源码所在位置的链接,如果有感兴趣的同学可以自行点击连接查看源码。Startup类比较常用,如果能够更深层次的了解其原理,对我们实际编程过程中会有很大的帮助,同时呼吁更多的小伙伴们深入阅读了解.NET Core的源码并分享出来。如有各位有疑问或者有了解的更透彻的,欢迎评论区提问或批评指导。

来源:脚本之家

链接:https://www.jb51.net/article/200322.htm

申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!

本文素材来自互联网

(编辑:应用网_阳江站长网)

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

热点阅读