定義
3つのインターフェースILogger
がILoggerProvider
ありILoggerFactory
ます。彼らの責任を見つけるためにソースコードを見てみましょう:
ILogger:特定のログレベルのログメッセージを書き込む責任があります。
ILoggerProvider:のインスタンスを作成する責任がありますILogger
(ILoggerProvider
ロガーの作成に直接使用することは想定されていません)
ILoggerFactory:ファクトリに 1つ以上ILoggerProvider
のを登録できます。ファクトリは、それらすべてを使用してのインスタンスを作成しますILogger
。ILoggerFactory
のコレクションを保持していますILoggerProviders
。
以下の例では、2つのプロバイダー(コンソールとファイル)をファクトリーに登録しています。ロガーを作成すると、ファクトリーはこれらのプロバイダーの両方を使用してロガーのインスタンスを作成します。
ILoggerFactory factory = new LoggerFactory().AddConsole(); // add console provider
factory.AddProvider(new LoggerFileProvider("c:\\log.txt")); // add file provider
Logger logger = factory.CreateLogger(); // <-- creates a console logger and a file logger
したがって、ロガー自体はのコレクションを維持ILogger
しており、ログメッセージをそれらすべてに書き込みます。Loggerのソースコードを見るとLogger
、配列ILoggers
(つまりLoggerInformation[]
)があり、同時にILogger
インターフェースを実装していることが確認できます。
依存性注入
MSのドキュメントには、ロガーを挿入するための2つの方法が用意されています。
1.工場への注入:
public TodoController(ITodoRepository todoRepository, ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApi.Controllers.TodoController");
}
Category = TodoApi.Controllers.TodoControllerでロガーを作成します。
2.ジェネリックを注入するILogger<T>
:
public TodoController(ITodoRepository todoRepository, ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
カテゴリー= TodoControllerの完全修飾型名でロガーを作成します
私の意見では、ドキュメントを混乱させるのは、非ジェネリックを注入することについては何も言及されていないということILogger
です。上記と同じ例では、非ジェネリックITodoRepository
を挿入していますが、に対して同じことを行わない理由は説明されていませんILogger
。
よると、マーク・シーマン:
インジェクションコンストラクターは、依存関係を受信するだけです。
ロガーを初期化する(SRPの違反)のはコントローラーの責任ではないため、ファクトリーをコントローラーに注入することは良いアプローチではありません。同時に、ジェネリックILogger<T>
を注入すると不要なノイズが追加されます。詳細については、Simple Injectorのブログを参照してください。ASP.NETCore DI抽象化の何が問題になっていますか?
注入する必要があるもの(少なくとも上記の記事によると)は総称ILogger
ではありませんが、それはMicrosoftの組み込みDIコンテナが実行できることではなく、サードパーティのDIライブラリを使用する必要があります。これら 2つのドキュメントでは、.NET Coreでサードパーティライブラリを使用する方法について説明しています。
これはニコラ・マロビッチによる別の記事で、彼はIoCの5つの法則を説明しています。
ニコラのIoCの第4法則
解決されるクラスのすべてのコンストラクターは、独自の依存関係のセットを受け入れる以外に実装があってはなりません。