[ASP.NET Core 3フレームワークの開示]サービスベアラシステム[4]:全体設計[下編]

22544 ワード

サービスホストとしてのIHostインタフェースを理解した後,次にホスト構築者としてのIHostBuilderインタフェースを認識する.以下のコードフラグメントに示すように、IHostBuilderインタフェースのコアメソッドBuildは、それによって構築されたIHostオブジェクトを提供するために使用される.また、辞書タイプの読み取り専用プロパティPropertiesもあり、共有データコンテナと見なすことができます.
public interface IHostBuilder
{    
    IDictionary<object, object> Properties { get; }
    IHost Build();
    …
}

典型的な設計モードとして、Builderモードは、最終的に構築されたオブジェクトに提供される前に、対応する前期設定を許可するのが一般的であり、IHostBuilderのIHostに対する構築も例外ではない.IHostBuilderインタフェースは、最終的に構築されたIHostオブジェクトに対応する設定を行うための一連の方法を提供しています.具体的な設定は、構成システムの設定と依存注入フレームワークの設定の2つの側面を主にカバーします.

一、構成システムに対する設定


IHostBuilderインタフェースの構成システムに対する設定は、コンフィギュレーション・システムおよびコンフィギュレーション・アプリケーション・メソッドに反映されます.前述の例の実証により、コンフィギュレーション・ホスト・メソッドに関連する構成は、主にサービス・ベアラ中に使用され、サービス・ホストの構成であることが分かった.ConfigureAppConfigurationメソッドは、ベアラのIHostedServiceサービスで使用されるアプリケーションの構成を設定します.しかし、前者は最終的に後者にマージされ、私たちが最終的に得た構成は実際には両者のマージの結果です.
public interface IHostBuilder
{
    IHostBuilder ConfigureHostConfiguration( Action configureDelegate); 
    IHostBuilder ConfigureAppConfiguration( Action configureDelegate);
    …
}

上記のコードクリップから、コンフィギュレーション・ホスト・コンフィギュレーション・メソッドは、コンフィギュレーション・ファイルが存在するディレクトリのパスを設定するなど、異なるコンフィギュレーション・ソースを登録したり、適切な設定をしたりするアクション・タイプの委任をパラメータとして提供していることがわかります.もう1つの方法ConfigureAppConfigurationのパラメータタイプはActionであり、最初のパラメータであるHostBuilderContextオブジェクトはサービスベアラに関するコンテキスト情報を携帯しており、このコンテキストを利用して構成システムを対象に設定することができます.
HostBuilderContextが携帯するコンテキストは主に2つの部分を含む:その1つは、ConfigureHostConfigurationメソッドを呼び出すことによって設定された宿主に対する構成;二つ目は、現在の負荷環境です.この2つのコンテキスト情報は、以下に示すコンフィギュレーションおよびHostingEnvironment属性にそれぞれ対応している.これに加えて、HostBuilderContextには共有データ辞書としてのProperties属性があります.構成システムの設定が現在のベアラコンテキストとは無関係である場合、この同名の拡張メソッドを呼び出すことができ、このメソッドが提供するパラメータは依然としてActionタイプの委任である.
public class HostBuilderContext
{
    public IConfiguration Configuration { get; set; }
    public IHostEnvironment HostingEnvironment { get; set; }
    public IDictionary<object, object> Properties { get; }
    public HostBuilderContext(IDictionary<object, object> properties);
}

public static class HostingHostBuilderExtensions
{
    public static IHostBuilder ConfigureAppConfiguration(this IHostBuilder hostBuilder, Action configureDelegate)
    => hostBuilder.ConfigureAppConfiguration((context, builder) =>configureDelegate(builder));
}

二、負荷環境


いずれのアプリケーションも、特定の環境に対して常に導入されています.ベアラ・サービスの導入環境をベアラ環境と呼びます.ベアラ環境はIHostEnvironmentインタフェースによって表され、HostBuilderContextのHostingEnvironmentプロパティはIHostEnvironmentオブジェクトを返します.次のコードフラグメントに示すように、環境名を表すEnvironmentNameプロパティに加えて、IHostEnvironmentインタフェースは現在のアプリケーション名を表すApplicationNameプロパティを定義します.
public interface IHostEnvironment
{
    string EnvironmentName { get; set; }
    string ApplicationName { get; set; }
    string ContentRootPath { get; set; }
    IFileProvider ContentRootFileProvider { get; set; }
}

あるものをコンパイルするとNET Coreプロジェクトの場合、提供されるコードファイル(.cs)ファイルはメタデータとIL命令に変換されて生成されたプログラムセットに保存され、他のファイルはプログラムセットの埋め込みリソースとしても使用できます.これらのプログラムセット向けのファイルに加えて、Webアプリケーションの3つの典型的な静的ファイル(JavaScript、CSS、ピクチャ)のような静的ファイルとして使用されるプログラムを静的ファイルとして提供するファイルもあります.これらの静的ファイルをコンテンツファイル「Content File」と呼びます.IHostEnvironmentインタフェースのContentRootPathは、これらのコンテンツファイルを格納するルートディレクトリが存在するパスを表し、もう1つのContentRootFileProviderプロパティは、そのパスを指すIFIleProviderオブジェクトに対応しており、ディレクトリの階層を取得したり、直接ファイルの内容を読み取ることができます.
開発、プレハブ、製品は3つの最も典型的なベアラ環境であり、「Development」、「Staging」、「Production」を用いて命名すれば、これら3つのベアラ環境に対する判断は、以下の3つの拡張方法(IsDevelopment、IsStaging、IsProduction)を用いて行うことができる.指定したIHostEnvironmentオブジェクトが特定の環境に属しているかどうかを判断する必要がある場合は、拡張メソッドIsEnvironmentを直接呼び出すことができます.与えられたコードフラグメントから,環境名の比較が大文字と小文字を区別しないことが容易に分かる.
public static class HostEnvironmentEnvExtensions
{
    public static bool IsDevelopment(this IHostEnvironment hostEnvironment)
        => hostEnvironment.IsEnvironment(Environments.Development);
    public static bool IsStaging(this IHostEnvironment hostEnvironment)
        => hostEnvironment.IsEnvironment(Environments.Staging);
    public static bool IsProduction(this IHostEnvironment hostEnvironment)
        => hostEnvironment.IsEnvironment(Environments.Production);

    public static bool IsEnvironment(this IHostEnvironment hostEnvironment, string environmentName)
        => string.Equals(hostEnvironment.EnvironmentName, environmentName, StringComparison.OrdinalIgnoreCase);
}

public static class Environments
{
    public static readonly string Development = "Development";
    public static readonly string Production = "Production";
    public static readonly string Staging = "Staging";
}

IHostEnvironmentオブジェクトが担持する3つの属性はすべて構成によって提供され、対応する構成項目名は「environment」と「contentRoot」と「applicationName」と呼ばれ、これらはHostDefaultsタイプの3つの静的読取り専用フィールドに対応している.IHostBuilderインタフェースのUseEnvironmentとUseContentRoot拡張メソッドの2つを呼び出して、環境名とコンテンツファイルのルートディレクトリパスを設定できます.与えられたコードフラグメントから,この方法は依然として呼び出されたConfigureHostConfiguration方法であることがわかる.アプリケーション名の表示設定が行われていない場合、エントリ・プログラム・セット名は現在のアプリケーション名として使用されます.
public static class HostDefaults
{
    public static readonly string EnvironmentKey = "environment";
    public static readonly string ContentRootKey = "contentRoot";
    public static readonly string ApplicationKey = "applicationName";
}

public static class HostingHostBuilderExtensions
{
    public static IHostBuilder UseEnvironment(this IHostBuilder hostBuilder, string environment)
    {
        return hostBuilder.ConfigureHostConfiguration(configBuilder =>
        {
            configBuilder.AddInMemoryCollection(new[]
            {
                new KeyValuePair<string, string>(HostDefaults.EnvironmentKey,environment)
            });
        });

        public static IHostBuilder UseContentRoot(this IHostBuilder hostBuilder, string contentRoot)
        {
            return hostBuilder.ConfigureHostConfiguration(configBuilder =>
            {
                configBuilder.AddInMemoryCollection(new[]
                {
                new KeyValuePair<string, string>(HostDefaults.ContentRootKey,
                    contentRoot))
                });
        });
    }
}

三、依存注入フレームに対する設定


ベアラサービスを含むすべての依存サービスは、依存注入フレームワークによって提供されるため、IHostBuilderインタフェースは、サービス登録を完了するためのより多くの方法を提供する.サービスを登録するために使用される方法のほとんどは、最終的に、現在のベアラコンテキストに対してサービスがターゲットとして登録できることを意味するアクションタイプの委任であるため、以下に示すConfigureServicesメソッドを呼び出す.登録されたサービスが現在のベアラコンテキストとは無関係である場合、Actionのタイプの委任オブジェクトである次のような同名の拡張メソッドを呼び出すことができます.
public interface IHostBuilder
{
    IHostBuilder ConfigureServices(Action configureDelegate);
    …
}

public static class HostingHostBuilderExtensions
{
    public static IHostBuilder ConfigureServices(this IHostBuilder hostBuilder, Action configureDelegate)
        => hostBuilder.ConfigureServices((context, collection) => configureDelegate(collection));
}

ログに関するプレゼンテーションでは、IHostBuilderインタフェースの拡張メソッドConfigureLoggingを呼び出し、ログフレームワークに対するコアサービスを登録しました.次のコードクリップは、この2つの拡張メソッドの再ロードの定義を示しています.この2つの方法の背後には、IServiceCollectionインタフェースを呼び出すAddLogging拡張メソッドによって登録された上記のConfigureServicesメソッドが依然として呼び出されていることがわかります.
public static class HostingHostBuilderExtensions
{
    public static IHostBuilder ConfigureLogging(this IHostBuilder hostBuilder, Action configureLogging)
        => hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(context, builder)));

    public static IHostBuilder ConfigureLogging(this IHostBuilder hostBuilder, Action configureLogging)
            => hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(builder)));
}

IHostBuilderインタフェースは、登録されているIServiceProviderFactoryオブジェクトを使用してサードパーティ依存注入フレームワークの統合を実現する2つのU s e ServiceProviderFactoryメソッドのリロードを提供します.このほか、このインタフェースには、IServiceProviderFactoryオブジェクトを登録するために作成された別のConfigureContainerが追加設定されています.
public interface IHostBuilder
{
    IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory);
    IHostBuilder UseServiceProviderFactory(Func> factory);
    IHostBuilder ConfigureContainer(Action configureDelegate);
}

個人的にはNET Core依存注入フレームワークは、ほとんどのアプリケーション開発のニーズを満たすことができるので、サードパーティ依存注入フレームワークとの統合はあまり必要ありません.依存注入コンテナとしてIServiceProviderを提供するためにDefaultServiceProviderFactoryを使用したオリジナルの依存注入フレームワークを知っています.この登録は、次の2つのUseDefaultServiceProvider拡張メソッドによって行われます.
public static class HostingHostBuilderExtensions
{
    public static IHostBuilder UseDefaultServiceProvider(this IHostBuilder hostBuilder, Action configure)
    => hostBuilder.UseDefaultServiceProvider((context, options) => configure(options));

    public static IHostBuilder UseDefaultServiceProvider(this IHostBuilder hostBuilder, Action configure)
    {
        return hostBuilder.UseServiceProviderFactory(context =>
        {
            var options = new ServiceProviderOptions();
            configure(context, options);
            return new DefaultServiceProviderFactory(options);
        });
    }
}

IHostBuilderインタフェースで定義されているコンフィギュレーションContainerメソッドによって提供されるパラメータは、Actionの委任オブジェクトのタイプです.TContainerBuilderの設定が現在のベアラコンテキストとは無関係であれば、次のような簡略化されたコンフィギュレーションContainer拡張メソッドを呼び出すこともできます.これは、Actionオブジェクトをパラメータとして1つだけ提供すればよいだけです.
public static class HostingHostBuilderExtensions
{
    public static IHostBuilder ConfigureContainer(this IHostBuilder hostBuilder, Action configureDelegate)
    {
        return hostBuilder.ConfigureContainer((context, builder) => configureDelegate(builder));
    }
}

四、宿主の作成と起動


IHostBuilderインタフェースには、IHostオブジェクトの作成と起動を同時に完了するStartAsync拡張メソッドと、StartAsyncメソッドの同期バージョンを持つStartAsync拡張メソッドもあります.
public static class HostingAbstractionsHostBuilderExtensions
{
    public static async Task StartAsync(this IHostBuilder hostBuilder, CancellationToken cancellationToken = default)
    {
        var host = hostBuilder.Build();
        await host.StartAsync(cancellationToken);
        return host;
    }

    public static IHost Start(this IHostBuilder hostBuilder) => hostBuilder.StartAsync().GetAwaiter().GetResult();
}

サービスベアラシステム[1]:長時間稼働を担うサービス[前編]サービスベアラシステム[2]:長時間稼働を担うサービス[下編]サービスベアラシステム[3]:全体設計[前編]サービスベアラシステム[4]:全体設計[下編]サービスベアラシステム[5]:ベアラサービス起動フロー[前編]サービスベアラシステム[6]:ベアラサービス起動フロー[下編]