.Net7 源码浅析之替换默认容器的原理

167 阅读2分钟

.Net7 源码浅析之替换默认容器的原理

以.Net中常用的IOC容器Autofac使用方法为例[源码](autofac/Examples: Example projects that consume and demonstrate Autofac IoC functionality and integration (github.com))

在ConfigureServices方法中调用AddAutofac()拓展方法 image.png

只是注入一个单例对象生命周期的IServiceProviderFactory<ContainerBuilder>接口实现 image.png

啊原来这么简单只要实现IServiceProviderFactory<ContainerBuilder>接口就能自定义容器了?

Autofac默认注入方法了解到这来接下来我们看.Net源码中关于IServiceProviderFactory<ContainerBuilder>是如何去内部运用的如何达到容器的原理

接上章从.Net7应用程序启动开始入手依次查看到

image.png

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负责所有代码注入服务的获取,这里被自定义实现后就达到了替换默认容器的原理

下一章再来拓展实现自定义容器

参考代码库来源

  1. dotnet/runtime dotnet/runtime: .NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps. (github.com)

  2. 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)

  3. autofac Examples autofac/Examples: Example projects that consume and demonstrate Autofac IoC functionality and integration (github.com)