2009-08-18 8 views
21

私は静的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 
    } 
} 

注:私はDependency Injection in .NET with examples?を読みましたが、これはインスタンスロガーを使用しているようです。

答えて

24

静的なロガーを挿入することはできません。インスタンスロガーに変更するか(可能であれば)、またはインスタンスロガーでラップする(静的メソッドを呼び出す)必要があります。静的クラスに何かを注入するのはかなり難しいです(何らかの理由で静的なコンストラクタを制御しないため)。そのため、私がパラメータとして注入したいすべてのオブジェクトを渡す傾向があります。

21

これは必ずしもそうではありません。限り、あなたの静的なロガーがする方法で公開されて:あなたが注入された、またはそれを実行する前に、適切なメソッド呼び出しにおけるDIコンテナの

  • インジェクション(ASPのようなもので言うWANTクラスの

    • インジェクションを.net global.asax Application_Startメソッド)、あなたはうまくいくはずです。

    次に例を示します。 DIについては、以下のクラスを取る:私のGlobal.asaxの中で、この場合には(あなたのアプリケーションのためのグローバルなスタートアップで、今

    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); 
         } 
    
    
        } 
    

    :ここ

    public class Logger : ILogger 
        { 
         public void Log(string stringToLog) 
         { 
          Console.WriteLine(stringToLog); 
         } 
        } 
    
        public interface ILogger 
        { 
         void Log(string stringToLog); 
        } 
    

    とすると、ロガーを必要とする私たちの静的なクラスです.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"); 
    
         } 
    

    そしてpresto!静的クラスでDIを使用して起動しています。

    誰かを助ける希望。私は多くの静的クラスを使用するアプリケーションを再作成しており、これをしばらく使用しています。

  • +5

    依存性の解決よりも依存性の解決策に似ています。静的クラスは現在、依存関係フレームワークの知識を持っています。しかし、それを避けるためにそれを適応させることは難しくありません。 (application_startで解決し、初期化でリゾルバを提供するのではなく、解決された依存関係で初期化してください。) –

    +0

    質問は、静的クラスを静的クラスに注入することです。ここでは、非静的インスタンスを静的クラスに挿入する方法について説明します。 これは前の回答の次のステートメントに対する応答のようです: "静的なクラスに何かを注入するのはかなり難しい" –

    +0

    これはロガーのような単純なものでは非常に複雑です。 – rolls

    0

    Loggerの仕組みはよく分かりませんが、一般的にはRequestServiceを使用してインスタンスを取得できます。たとえば、抽象クラスの場合:

    this.HttpContext.RequestServices.GetService(typeof(YOUR_SERVICE)); 
    

    コントローラでは、HttpContextにアクセスできます。

    第二の方法は、あなたがこれを行うことができますスタートアップ、例のためにそれを使用している:

    serviceCollectionはDOTNETコアに IServiceCollectionある
    serviceCollection.AddScoped(typeof(ICmsDataContext), typeof(TDbContext)); 
    

    希望しました。

    1

    これは、静的なロガーの機能を「注入」するための非常に簡単な方法です。

    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 
        } 
    }