静的なLoggerクラスを呼び出す静的なクラスがあります。
例えば
static class DoesStuffStatic
{
public static void DoStuff()
{
try
{
//something
}
catch(Exception e)
{
//do stuff;
Logger.Log(e);
}
}
}
static class Logger
{
public static void Log(Exception e)
{
//do stuff here
}
}
ロガーを静的クラスに挿入するにはどうすればよいですか?
注:私は 例を含む.NETでの依存性注入? を読みましたが、これはインスタンスロガーを使用しているようです。
静的ロガーを挿入することはできません。これをインスタンスロガーに変更する(可能な場合)か、インスタンスロガーでラップする(静的を呼び出す)必要があります。また、静的クラスに何かを注入することはかなり困難です(静的コンストラクタを制御しないため)。そのため、注入するすべてのオブジェクトをパラメーターとして渡します。
これは必ずしもそうではありません。静的ロガーが次のメソッドを公開している限り:
ここに例があります。 DIには次のクラスを使用します。
public class Logger : ILogger
{
public void Log(string stringToLog)
{
Console.WriteLine(stringToLog);
}
}
public interface ILogger
{
void Log(string stringToLog);
}
そして、ここにロガーを必要とする静的クラスがあります:
public static class SomeStaticClass
{
private static IKernel _diContainer;
private static ILogger _logger;
public static void Init(IKernel dIcontainer)
{
_diContainer = dIcontainer;
_logger = _diContainer.Get<ILogger>();
}
public static void Log(string stringToLog)
{
_logger.Log(stringToLog);
}
}
これで、アプリのグローバルスタートアップ(この場合はmy global.asax.cs)で、DIコンテナーをインスタンス化して、静的クラスに渡すことができます。
public class Global : Ninject.Web.NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
return Container;
}
static IKernel Container
{
get
{
var standardKernel = new StandardKernel();
standardKernel.Bind<ILogger>().To<Logger>();
return standardKernel;
}
}
void Application_Start(object sender, EventArgs e)
{
SomeStaticClass.Init(Container);
SomeStaticClass.Log("Dependency Injection with Statics is totally possible");
}
そしてプレスト!これで、静的クラスでDIを使用できるようになりました。
それが誰かを助けることを願っています。多くの静的クラスを使用するアプリケーションを作り直しているところですが、しばらくの間、これをうまく利用しています。
これは、静的ロガーの機能を「注入」する非常に簡単な方法です。
public static class Logger
{
private static Action<string, Exception> _logError;
public static bool Initialised;
public static void InitLogger(Action<string, Exception, bool> logError)
{
if(logError == null) return;
_logError = logError
Initialised = true;
}
public static void LogError(string msg, Exception e = null)
{
if (_logError != null)
{
try
{
_logError.Invoke(msg, e);
}
catch (Exception){}
}
else
{
Debug.WriteLine($"LogError() Msg: {msg} Exception: {e}");
}
}
}
public class MainViewModel
{
public MainViewModel()
{
//Inject the logger so we can call it globally from anywhere in the project
Logger.InitLogger(LogError);
}
public void LogError(string msg, Exception e = null)
{
//Implementation of logger
}
}
ロガーがどのように動作するかはわかりませんが、通常はRequestServiceを使用してインスタンスを取得できます。たとえば、抽象クラスでは:
this.HttpContext.RequestServices.GetService(typeof(YOUR_SERVICE));
HttpContextにアクセスできるコントローラーの場合は可能です。
2番目の方法は、たとえばStartupで使用する方法で、これを行うことができます。
serviceCollection.AddScoped(typeof(ICmsDataContext), typeof(TDbContext));
ここで、serviceCollectionは、dotnet CoreではIServiceCollectionです。
お役に立てば幸いです。