UseStartup加载Start类过程
这个过程主要是利用了依赖注入原理。
WebHostBuilder类有一个扩展WebHostBuilderExtensions,在这个扩展中对WebHostBuilder的方法进行了扩展,里面就包含UseStartup()方法,这个方法里将Start服务添加进去:
/// <summary>
/// Specify the startup type to be used by the web host.
/// </summary>
/// <param name="hostBuilder">The <see cref="IWebHostBuilder"/> to configure.</param>
/// <param name="startupType">The <see cref="Type"/> to be used.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
{
var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name;
hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName);
// Light up the GenericWebHostBuilder implementation
if (hostBuilder is ISupportsStartup supportsStartup)
{
return supportsStartup.UseStartup(startupType);
}
return hostBuilder
.ConfigureServices(services =>
{
if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
{
services.AddSingleton(typeof(IStartup), startupType);
}
else
{
services.AddSingleton(typeof(IStartup), sp =>
{
var hostingEnvironment = sp.GetRequiredService<IHostEnvironment>();
return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName));
});
}
});
}
这段代码里如果对AddSingleton()方法不理解的,可以参考文章C# 依赖注入IServiceCollection的AddSingleton方法使用
上面的代码是通过进一步调用WebHostBuilder的ConfigureServices()方法,这个方法的微软源码是这样子的:
/// <summary>
/// Adds a delegate for configuring additional services for the host or web application. This may be called
/// multiple times.
/// </summary>
/// <param name="configureServices">A delegate for configuring the <see cref="IServiceCollection"/>.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
{
if (configureServices == null)
{
throw new ArgumentNullException(nameof(configureServices));
}
return ConfigureServices((_, services) => configureServices(services));
}
/// <summary>
/// Adds a delegate for configuring additional services for the host or web application. This may be called
/// multiple times.
/// </summary>
/// <param name="configureServices">A delegate for configuring the <see cref="IServiceCollection"/>.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices)
{
_configureServices += configureServices;
return this;
}
WebHostBuilder中有个私有变量(它是一个delegate委托):
private Action<WebHostBuilderContext, IServiceCollection> _configureServices;
委托是可以做"+="操作的,也就是可以不断地往这个委托里加很多委托。这就是ConfigureServices干的事情。
WebHostBuilder最后会去调用Build()方法。在Build()方法内会调用私有方法BuildCommonServices(),在方法内会创建传说中非常重要的IServiceCollection服务容器实例:
var services = new ServiceCollection();
在这个私有方法里它最后会执行这么一句话:
_configureServices?.Invoke(_context, services);
它表示会不断地执行_configureServices委托中所有通过"+="添加了的委托程序,实现向服务容器IServiceCollection里添加服务的功能。
另外,BuildCommonServices()会将这个服务容器返回出来,应用当中会拷贝这个服务容器:
var hostingServices = BuildCommonServices(out var hostingStartupErrors);
var applicationServices = hostingServices.Clone();
var hostingServiceProvider = GetProviderFromFactory(hostingServices);