.net 6.0 依赖注入容器使用autofac 源码分析过程
一、 netCore 6.0 的源码下载
地址如下:https://github.com/dotnet/
可以用GIT 下载 :git clone --recursive https://github.com/dotnet/aspnetcore.git
内容如下图所示:
其中aspnetcore 和runtime 是源码的主要工程。
二、netCore 6.0 的引用源码地址
引用的地址:https://github.com/dotnet/runtime/tree/main/src/libraries
三、webapi 项目创建
var builder = WebApplication.CreateBuilder(args);
源码如下:
/// <summary>
/// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with preconfigured defaults.
/// </summary>
/// <param name="args">Command line arguments</param>
/// <returns>The <see cref="WebApplicationBuilder"/>.</returns>
public static WebApplicationBuilder CreateBuilder(string[] args) =>
new(new() { Args = args });
用了一个静态函数来创建 WebApplicationBuilder 对象;
实例化过程源码如下:
internal WebApplicationBuilder(WebApplicationOptions options, Action<IHostBuilder>? configureDefaults = null)
{
var configuration = new ConfigurationManager();
configuration.AddEnvironmentVariables(prefix: "ASPNETCORE_");
_hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
{
Args = options.Args,
ApplicationName = options.ApplicationName,
EnvironmentName = options.EnvironmentName,
ContentRootPath = options.ContentRootPath,
Configuration = configuration,
});
// Set WebRootPath if necessary
if (options.WebRootPath is not null)
{
Configuration.AddInMemoryCollection(new[]
{
new KeyValuePair<string, string?>(WebHostDefaults.WebRootKey, options.WebRootPath),
});
}
// Run methods to configure web host defaults early to populate services
var bootstrapHostBuilder = new BootstrapHostBuilder(_hostApplicationBuilder);
// This is for testing purposes
configureDefaults?.Invoke(bootstrapHostBuilder);
bootstrapHostBuilder.ConfigureWebHostDefaults(webHostBuilder =>
{
// Runs inline.
webHostBuilder.Configure(ConfigureApplication);
webHostBuilder.UseSetting(WebHostDefaults.ApplicationKey, _hostApplicationBuilder.Environment.ApplicationName ?? "");
webHostBuilder.UseSetting(WebHostDefaults.PreventHostingStartupKey, Configuration[WebHostDefaults.PreventHostingStartupKey]);
webHostBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, Configuration[WebHostDefaults.HostingStartupAssembliesKey]);
webHostBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, Configuration[WebHostDefaults.HostingStartupExcludeAssembliesKey]);
},
options =>
{
// We've already applied "ASPNETCORE_" environment variables to hosting config
options.SuppressEnvironmentConfiguration = true;
});
// This applies the config from ConfigureWebHostDefaults
// Grab the GenericWebHostService ServiceDescriptor so we can append it after any user-added IHostedServices during Build();
_genericWebHostServiceDescriptor = bootstrapHostBuilder.RunDefaultCallbacks();
// Grab the WebHostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then
// grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection.
var webHostContext = (WebHostBuilderContext)bootstrapHostBuilder.Properties[typeof(WebHostBuilderContext)];
Environment = webHostContext.HostingEnvironment;
Host = new ConfigureHostBuilder(bootstrapHostBuilder.Context, Configuration, Services);
WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services);
}
其中ConfigureHostBuilder 对象 Host 就是用来配置autofac 容器的主要对象;
四 、autofac 容器使用
autofac 在unget 中搜Autofac.Extensions.Dependen 并安装;
使用方法如下:
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
其中AutofacServiceProviderFactory 定义如下;
public class AutofacServiceProviderFactory : IServiceProviderFactory<ContainerBuilder>{}
源码如下:
public IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory) where TContainerBuilder : notnull
{
if (factory is null)
{
throw new ArgumentNullException(nameof(factory));
}
_serviceProviderFactory = new ServiceProviderFactoryAdapter<TContainerBuilder>(factory);
return this;
}
定义的适配类源码如下:
private sealed class ServiceProviderFactoryAdapter<TContainerBuilder> : IServiceProviderFactory<object> where TContainerBuilder : notnull
{
private readonly IServiceProviderFactory<TContainerBuilder> _serviceProviderFactory;
public ServiceProviderFactoryAdapter(IServiceProviderFactory<TContainerBuilder> serviceProviderFactory)
{
_serviceProviderFactory = serviceProviderFactory;
}
public object CreateBuilder(IServiceCollection services) => _serviceProviderFactory.CreateBuilder(services);
public IServiceProvider CreateServiceProvider(object containerBuilder) => _serviceProviderFactory.CreateServiceProvider((TContainerBuilder)containerBuilder);
}
在调用 WebApplication Builder() 过程
public WebApplication Build()
{
// ConfigureContainer callbacks run after ConfigureServices callbacks including the one that adds GenericWebHostService by default.
// One nice side effect is this gives a way to configure an IHostedService that starts after the server and stops beforehand.
_hostApplicationBuilder.Services.Add(_genericWebHostServiceDescriptor);
Host.ApplyServiceProviderFactory(_hostApplicationBuilder);
_builtApplication = new WebApplication(_hostApplicationBuilder.Build());
return _builtApplication;
}
接着 Host 对象调用ApplyServiceProviderFactor() 的过程如下:
internal void ApplyServiceProviderFactory(HostApplicationBuilder hostApplicationBuilder)
{
if (_serviceProviderFactory is null)
{
// No custom factory. Avoid calling hostApplicationBuilder.ConfigureContainer() which might override default validation options.
// If there were any callbacks supplied to ConfigureHostBuilder.ConfigureContainer(), call those with the IServiceCollection.
foreach (var action in _configureContainerActions)
{
action(_context, _services);
}
return;
}
void ConfigureContainerBuilderAdapter(object containerBuilder)
{
foreach (var action in _configureContainerActions)
{
action(_context, containerBuilder);
}
}
hostApplicationBuilder.ConfigureContainer(_serviceProviderFactory, ConfigureContainerBuilderAdapter);
}
其中 hostApplicationBuilder.ConfigureContainer()源码在 HostApplicationBuilder.cs
https://github.com/dotnet/runtime/blob/e8b149109c8b04161b83d0e4c997b63759c6d936/src/libraries/Microsoft.Extensions.Hosting/src/
如下图所示:
记录一下,调用过程;