Asp.NetCore起動プロセス説明(四)
12029 ワード
Asp.NetCore内DI(DependencyInjection)はプロジェクトの終始を貫き、Aspを学ぶ.NetCoreはDIを越えられない.以下、DIはAspで説明する.Net Core内のプロセス
Asp.Net core 3.0以下には、IServiceProviderFactoryのデフォルト実装と、IStartupの2つのカスタム置換DIコンテナがある.Configure関数戻り値の変更
WebHostBuilderを表示Build
BuildCommonServices関数の再フォロー
考え方が簡単で、DIを登録し、IServiceProviderに戻ってHostコンテナに渡し、IServiceProviderFactoryを見つけ、タイプがD e f a ultServiceProviderFactoryではないと判断すると、DIを変換し、最後に新しいIServiceProviderに戻る.
WebHostBuilder.ConfigureServices内のDI登録がデフォルトで実装されているIServiceProviderFactory IServiceProviderFactoryのプロセスはIServiceProviderFactoryである.CreateBuilder->IServiceProviderFactory.CreateServiceProviderは、まずDIコンテナIServiceCollectionをカスタムコンテナに変換し、カスタムコンテナをIServiceProviderに変換し、最後にルートノードのIServiceProviderに依存すればよい
IServiceProviderFactoryの登録には論理WebHostBuilderがあります.UseDefaultServiceProviderからソースへ
異曲同工の妙は,これ以上くどくど述べない.
おなじみのWebHostBuilderを開くかBuildCommonServices
IStartupからDIへの登録
WebHostBuilderを確認してください.Build
見てみろInitializeコード
見てみろEnsureApplicationServicesコード
IStartupインタフェースのインスタンスを取得し、IStartupを呼び出す.ConfigureServicesはIServiceProviderインスタンスを返します
Asp.Net Core 3.0以下の設計コードは混乱しすぎてAsp.Net Core 3.0が始まり、DIに代わる流れが簡潔になりました
デフォルトのプログラムエントリ
ホストを表示します.CreateDefaultBuilder
HostBuilderに向かいます.Build
HostBuilderを表示CreateServiceProvider
ここには_ServiceProviderFactory、定義に移動
対応するパラメータには、2つの関数が異なるリロードされたUseServiceProviderFactoryがあります.
レモンの大物はAspと言った.Net CoreはせめてDIに置き換えられるところが3箇所~もう1箇所ソースコードを見てみましたがIApplicationBuilderFactoryかな
ここでCreateBuilderはIApplicationBuilder IApplicationBuilderのIocオブジェクトを返しますここで設定できます
もし内容に対して交流と学习のがあるならば、プラスすることができます.Netアプリケーションフレームワーク交流グループ、グループ番号386092459
asp.Netcore 3.0以下
Asp.Net core 3.0以下には、IServiceProviderFactoryのデフォルト実装と、IStartupの2つのカスタム置換DIコンテナがある.Configure関数戻り値の変更
1、IServiceProviderFactory
WebHostBuilderを表示Build
public IWebHost Build()
{
var hostingServices = BuildCommonServices(out var hostingStartupErrors);
var applicationServices = hostingServices.Clone();
var hostingServiceProvider = GetProviderFromFactory(hostingServices);
AddApplicationServices(applicationServices, hostingServiceProvider);
var host = new WebHost(
applicationServices,
hostingServiceProvider,
_options,
_config,
hostingStartupErrors);
try
{
host.Initialize();
//
return host;
}
catch
{
host.Dispose();
throw;
}
IServiceProvider GetProviderFromFactory(IServiceCollection collection)
{
var provider = collection.BuildServiceProvider();
var factory = provider.GetService>();
if (factory != null && !(factory is DefaultServiceProviderFactory))
{
using (provider)
{
return factory.CreateServiceProvider(factory.CreateBuilder(collection));
}
}
return provider;
}
}
BuildCommonServices関数の再フォロー
private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
{
var services = new ServiceCollection();
//
services.AddTransient, DefaultServiceProviderFactory>();
_configureServices?.Invoke(_context, services);
return services;
}
考え方が簡単で、DIを登録し、IServiceProviderに戻ってHostコンテナに渡し、IServiceProviderFactoryを見つけ、タイプがD e f a ultServiceProviderFactoryではないと判断すると、DIを変換し、最後に新しいIServiceProviderに戻る.
public interface IServiceProviderFactory
{
TContainerBuilder CreateBuilder(IServiceCollection services);
IServiceProvider CreateServiceProvider(TContainerBuilder
containerBuilder);
}
WebHostBuilder.ConfigureServices内のDI登録がデフォルトで実装されているIServiceProviderFactory IServiceProviderFactoryのプロセスはIServiceProviderFactoryである.CreateBuilder->IServiceProviderFactory.CreateServiceProviderは、まずDIコンテナIServiceCollectionをカスタムコンテナに変換し、カスタムコンテナをIServiceProviderに変換し、最後にルートノードのIServiceProviderに依存すればよい
IServiceProviderFactoryの登録には論理WebHostBuilderがあります.UseDefaultServiceProviderからソースへ
public static IWebHostBuilder UseDefaultServiceProvider(this IWebHostBuilder hostBuilder, Action configure)
{
return hostBuilder.ConfigureServices((context, services) =>
{
var options = new ServiceProviderOptions();
configure(context, options);
// IServiceProviderFactory
services.Replace(ServiceDescriptor.Singleton>(new DefaultServiceProviderFactory(options)));
});
}
異曲同工の妙は,これ以上くどくど述べない.
2、IStartup.Configure
おなじみのWebHostBuilderを開くかBuildCommonServices
private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
{
var services = new ServiceCollection();
//
if (!string.IsNullOrEmpty(_options.StartupAssembly))
{
try
{
var startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);
if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
{
services.AddSingleton(typeof(IStartup), startupType);
}
else
{
services.AddSingleton(typeof(IStartup), sp =>
{
var hostingEnvironment = sp.GetRequiredService();
var methods = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName);
return new ConventionBasedStartup(methods);
});
}
}
catch (Exception ex)
{
var capture = ExceptionDispatchInfo.Capture(ex);
services.AddSingleton(_ =>
{
capture.Throw();
return null;
});
}
}
_configureServices?.Invoke(_context, services);
return services;
}
IStartupからDIへの登録
WebHostBuilderを確認してください.Build
public IWebHost Build()
{
var hostingServices = BuildCommonServices(out var hostingStartupErrors);
var applicationServices = hostingServices.Clone();
var hostingServiceProvider = GetProviderFromFactory(hostingServices);
var host = new WebHost(
applicationServices,
hostingServiceProvider,
_options,
_config,
hostingStartupErrors);
try
{
host.Initialize(); //
//
return host;
}
catch
{
host.Dispose();
throw;
}
}
見てみろInitializeコード
public void Initialize()
{
try
{
EnsureApplicationServices();
}
catch (Exception ex)
{
// EnsureApplicationServices may have failed due to a missing or throwing Startup class.
if (_applicationServices == null)
{
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
}
if (!_options.CaptureStartupErrors)
{
throw;
}
_applicationServicesException = ExceptionDispatchInfo.Capture(ex);
}
}
見てみろEnsureApplicationServicesコード
private void EnsureApplicationServices()
{
if (_applicationServices == null)
{
EnsureStartup();
_applicationServices = _startup.ConfigureServices(_applicationServiceCollection);
}
}
private void EnsureStartup()
{
if (_startup != null)
{
return;
}
_startup = _hostingServiceProvider.GetService();
if (_startup == null)
{
throw new InvalidOperationException($"No application configured. Please specify startup via IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, injecting {nameof(IStartup)} or specifying the startup assembly via {nameof(WebHostDefaults.StartupAssemblyKey)} in the web host configuration.");
}
}
IStartupインタフェースのインスタンスを取得し、IStartupを呼び出す.ConfigureServicesはIServiceProviderインスタンスを返します
Asp.Net Core 3.0以上
Asp.Net Core 3.0以下の設計コードは混乱しすぎてAsp.Net Core 3.0が始まり、DIに代わる流れが簡潔になりました
デフォルトのプログラムエントリ
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
});
}
ホストを表示します.CreateDefaultBuilder
public static IHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new HostBuilder();
//
return builder;
}
HostBuilderに向かいます.Build
public IHost Build()
{
//
CreateServiceProvider();
return _appServices.GetRequiredService();
}
HostBuilderを表示CreateServiceProvider
private void CreateServiceProvider()
{
var services = new ServiceCollection();
//
var containerBuilder = _serviceProviderFactory.CreateBuilder(services);
foreach (var containerAction in _configureContainerActions)
{
containerAction.ConfigureContainer(_hostBuilderContext, containerBuilder);
}
_appServices = _serviceProviderFactory.CreateServiceProvider(containerBuilder);
if (_appServices == null)
{
throw new InvalidOperationException($"The IServiceProviderFactory returned a null IServiceProvider.");
}
// resolve configuration explicitly once to mark it as resolved within the
// service provider, ensuring it will be properly disposed with the provider
_ = _appServices.GetService();
}
ここには_ServiceProviderFactory、定義に移動
public class HostBuilder : IHostBuilder
{
//
private IServiceFactoryAdapter _serviceProviderFactory = new ServiceFactoryAdapter(new DefaultServiceProviderFactory());
}
対応するパラメータには、2つの関数が異なるリロードされたUseServiceProviderFactoryがあります.
public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory)
{
_serviceProviderFactory = new ServiceFactoryAdapter(factory ?? throw new ArgumentNullException(nameof(factory)));
return this;
}
public IHostBuilder UseServiceProviderFactory(Func> factory)
{
_serviceProviderFactory = new ServiceFactoryAdapter(() => _hostBuilderContext, factory ?? throw new ArgumentNullException(nameof(factory)));
return this;
}
後記
レモンの大物はAspと言った.Net CoreはせめてDIに置き換えられるところが3箇所~もう1箇所ソースコードを見てみましたがIApplicationBuilderFactoryかな
public interface IApplicationBuilderFactory
{
IApplicationBuilder CreateBuilder(IFeatureCollection serverFeatures);
}
ここでCreateBuilderはIApplicationBuilder IApplicationBuilderのIocオブジェクトを返しますここで設定できます
もし内容に対して交流と学习のがあるならば、プラスすることができます.Netアプリケーションフレームワーク交流グループ、グループ番号386092459