私はASP.NETCoreを使用しています。このようなログメカニズムはフレームワークによってすでに提供されていることは知っていますが、これを使用して問題を説明しています。
ロギングのタイプがわからないため(DBに格納されているため)、一種のファクトリパターンを使用してLoggerクラスを構築しています。
ILogger契約
Log(string msg)
次に、LoggerFactoryは、DBから渡されたパラメータに基づいてロガーを作成した後、ILoggerを返します。
public class LoggerFactory
{
public static Contracts.ILogger BuildLogger(LogType type)
{
return GetLogger(type);
}
//other code is omitted, GetLogger will return an implementation of the related logger
さて、ロガーを使用する必要があるときは、次のようにする必要があります。
public class MyService
{
private ILogger _logger
public MyService()
{
_logger = LoggerFactory.BuildLogger("myType");
}
ただし、インスタンス化せずにクラスを保持するつもりです。MyServiceでコンストラクタDIを使用する必要があり、Startupへのすべての依存関係を挿入する必要があります。
services.AddTransient<Contracts.ILogger, LoggerFactory.BuildLogger("param") > ();
しかし、これは機能しません。具体的な実装を渡す必要があります。 DIを使用してそれを機能させる方法、それを実装するためのより良いアプローチはありますか?
あなたのアプローチにはいくつかの誤りがあります:
LoggerFactory
タイプに依存しています。ILogger
があなたの消費者が依存している本当のサービスであるという事実を隠します。これにより、システムのテスト、保守が困難になり、オブジェクトグラフの分析が複雑になります。代わりに、サービスは次のようになります。
public class MyService
{
private ILogger _logger;
public MyService(ILogger logger)
{
_logger = logger;
}
}
これにより、ILogger
に依存するすべてのコンシューマーが劇的に簡素化されます。これは、ILogger
に対して正しいMyService
を取得することが、この知識を持つ正しい場所である Composition Root の責任になることも意味します。
ただし、組み込みコンテナーはILogger
ライブラリに他のコンストラクターの依存関係も自動配線させながら、.
ASP.NET Core DIコンテナーでは、デリゲートを使用してのみサービスを手動で配線できます。例えば:
services.AddTransient<MyService>(c => new MyService(
BuildLogger(typeof(MyService).Name),
c.GetRequiredService<ISomeOtherDependency>(),
c.GetRequiredService<IYetAnotherOne>());