.Net7 源码浅析之替换默认容器的原理
以.Net中常用的IOC容器Autofac使用方法为例[源码](autofac/Examples: Example projects that consume and demonstrate Autofac IoC functionality and integration (github.com))
在ConfigureServices方法中调用AddAutofac()拓展方法
只是注入一个单例对象生命周期的IServiceProviderFactory<ContainerBuilder>接口实现
啊原来这么简单只要实现IServiceProviderFactory<ContainerBuilder>接口就能自定义容器了?
Autofac默认注入方法了解到这来接下来我们看.Net源码中关于IServiceProviderFactory<ContainerBuilder>是如何去内部运用的如何达到容器的原理
接上章从.Net7应用程序启动开始入手依次查看到
GetProviderFromFactory()源码如下,从默认容器中拿到IServiceProviderFactory<IServiceCollection>的注入实例,然后判断是否默认容器提供DefaultServiceProviderFactory,非默认容器则直接返回实际容器CreateServiceProvider(TContainerBuilder containerBuilder)方法的返回值IServiceProvider。
由上一章可知.Net7中的容器获取都是基于IServiceProvider去定义的
static IServiceProvider GetProviderFromFactory(IServiceCollection collection)
{
var provider = collection.BuildServiceProvider();
var factory = provider.GetService<IServiceProviderFactory<IServiceCollection>>();
if (factory != null && factory is not DefaultServiceProviderFactory)
{
using (provider)
{
return factory.CreateServiceProvider(factory.CreateBuilder(collection));
}
}
return provider;
}
再来查看IServiceProviderFactory<TContainerBuilder>的接口定义,只有CreateBuilder(IServiceCollection services)和CreateServiceProvider(TContainerBuilder containerBuilder)两个方法,再结合GetProviderFromFactory()方法的内部实现发现其实就是把默认的IServiceCollection对象都通过CreateBuilder(IServiceCollection services)传入内部然后调用CreateServiceProvider(TContainerBuilder containerBuilder)返回对应的IServiceProvider实现对象
public interface IServiceProviderFactory<TContainerBuilder> where TContainerBuilder : notnull
{
/// <summary>
/// Creates a container builder from an <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The collection of services</param>
/// <returns>A container builder that can be used to create an <see cref="IServiceProvider"/>.</returns>
TContainerBuilder CreateBuilder(IServiceCollection services);
/// <summary>
/// Creates an <see cref="IServiceProvider"/> from the container builder.
/// </summary>
/// <param name="containerBuilder">The container builder</param>
/// <returns>An <see cref="IServiceProvider"/></returns>
IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder);
}
分析完上述代码其实替换默认容器的原理我们大概已经明白 接下来把整个步骤重新梳理一下
概况
1.源码Service中默认IServiceProviderFactory<ContainerBuilder>的实现为DefaultServiceProviderFactory
2.注入的IServiceProviderFactory<ContainerBuilder>的对应实现替换默认的DefaultServiceProviderFactory
3.IServiceProviderFactory的CreateServiceProvider方法返回对应的自定义的IServiceProvider对象实现
4.IServiceProvider负责所有代码注入服务的获取,这里被自定义实现后就达到了替换默认容器的原理
下一章再来拓展实现自定义容器
参考代码库来源
-
dotnet/runtime dotnet/runtime: .NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps. (github.com)
-
dotnet/aspnetcore dotnet/aspnetcore: ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux. (github.com)
-
autofac Examples autofac/Examples: Example projects that consume and demonstrate Autofac IoC functionality and integration (github.com)