.NET 汎用ホスト(Generic Host)とは
''ホスト'' とは、次のようなアプリのリソースと有効期間機能をカプセル化するオブジェクトです。
依存関係の挿入 (DI)
ログの記録
構成
アプリのシャットダウン
IHostedService の実装
やってみよう。
NuGet
Microsoft.Extensions.Hosting をパッケージに追加します。
ホストの作成
ホストを作るにはビルダーを使います。
HostApplicationBuilder hostBuilder = Host.CreateApplicationBuilder(args);
Host.CreateDefaultBuilder()
もあるけど?
依存関係の挿入(DI)
サービスコンテナで依存関係を挿入できry
構成(Configuration)
Host.CreateApplicationBuilder(String[]) メソッドにより、優先度の高い方から低い方へ、次の順序でアプリの既定の構成が提供されます。
- コマンドライン構成プロバイダーを使用するコマンドライン引数。
- 環境変数構成プロバイダーを使用する環境変数。
- Development 環境でアプリが実行される際の App シークレット。
- JSON 構成プロバイダーを使用する appsettings.json。
- JSON 構成プロバイダーを使用する appsettings.Environmentjson。 たとえば、appsettings.Production.json および appsettings.Development.json。
- ChainedConfigurationProvider: 既存の IConfiguration をソースとして追加します。
アプリ独自の設定をappsettings.jsonに定義。
{
"lang": "ja",
"LogOptions": {
"SingleLine": true,
"TimestampFormat": "yyyy-MM-dd HH:mm:ss "
}
}
ログの記録(Logging)のログレベルは、環境毎のファイルに定義。
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsft": "Information"
}
}
}
appsettings.jsonの内容をマップするクラスを実装。
internal class AppSettings
{
public string Lang { set; get; } = "en";
public LogOptions LogOptions { set; get; } = new LogOptions();
}
internal class LogOptions
{
public bool SingleLine { set; get; } = false;
public string TimestampFormat { set; get; } = "HH:mm:ss ";
}
設定をマップする
var appSettings = hostBuilder.Configuration.Get<AppSettings>() ?? new AppSettings();
設定の一部分だけをマップする
var logOptions = hostBuilder.Configuration.GetSection(nameof(LogOptions)).Get<LogOptions>() ?? new LogOptions();
構成(Configuration)は、サービスコンテナンに登録されてます。
//using IHost host = hostBuilder.Build();
var configuration = host.Services.GetService<IConfiguration>()!;
ログの記録(Logging)
例として、ログプロバイダーとしてSimpleConsoleを追加します。(log4net、Nlogなども利用可)
ログレベルは、appsettings.Development.jsonの /Logging/LogLevel
に設定した内容が反映されます。
出力オプションは構成(Configuration)から取得した内容を設定しています。
hostBuilder.Logging.ClearProviders().AddSimpleConsole(options =>
{
options.SingleLine = appSettings.LogOptions.SingleLine;
options.TimestampFormat = appSettings.LogOptions.TimestampFormat;
});
ロガーは、サービスコンテナンに登録されてます。
//using IHost host = hostBuilder.Build();
var logger = host.Services.GetService<ILogger<Program>>()!;
ローカライズ
2024/11/18更新!
NuGet
リソースファイル追加
<root>
<data name="hello_world" xml:space="preserve">
<value>こんにちは、世界!</value>
</data>
</root>
<root>
<data name="hello_world" xml:space="preserve">
<value>Hello World!</value>
</data>
</root>
サービス作成
internal class MessageService(IStringLocalizer<MessageResources> localizer)
{
internal string this[string key]
{
get
{
return localizer[key];
}
}
}
ホストの作成
// カルチャの設定
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(appSettings.Lang);
// ローカライゼーションサービスの追加
hostBuilder.Services.AddLocalization();
// MessageServiceを登録
hostBuilder.Services.AddSingleton<MessageService>();
次 で利用してみます。
IHostedServiceの実装
ホストが起動すると、サービス コンテナーのホステッド サービスのコレクションに登録されている IHostedService の各実装で IHostedService.StartAsync が呼び出されます。
アプリの相互依存するすべてのリソースを 1 つのオブジェクトに含める主な理由は、アプリの起動と正常なシャットダウンの制御の有効期間の管理のためです。
IHostedService
の実装HostedService
を作成します。
internal class HostedService(
//コンストラクタの引数はサービスコンテナによってDIされる
IHostApplicationLifetime hostApplicationLifetime,
IHostEnvironment environment,
IHostLifetime hostLifetime,
IConfiguration configuration,
ILogger<HostedService> logger,
MessageService messageService
) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
logger.LogTrace("HostedService.StartAsync");
// 構成ファイルの中から独自設定を取得
var appSettings = configuration.Get<AppSettings>() ?? new AppSettings();
logger.LogDebug(appSettings.Lang);
// ローカライズされたメッセージの取得
logger.LogDebug(messageService["hello_world"]);
// アプリを終了する
hostApplicationLifetime.StopApplication();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
logger.LogTrace("HostedService.StopAsync");
return Task.CompletedTask;
}
}
実装したHostedService
をサービスコンテナンに登録します。
hostBuilder.Services.AddHostedService<HostedService>();
IHostEnvironment
TODO
IHostApplicationLifetime
アプリケーションを終了するのにつかう
IHostLifetime
TODO
ホストの起動
using IHost host = hostBuilder.Build();
await host.RunAsync();