2009-08-21 5 views
4

Soll ein Logging-Framework in Klassen eingefügt werden, die sie benötigen, oder sollte jede Klasse, die es benötigt, das Framework kennen und es direkt verwenden? Ich benutze Log4Net und derzeit spreche ich einen Dienst ein, der dieses Framework in die Klassen einbindet, die protokolliert werden müssen. Wissen Sie, dass Logging sich wahrscheinlich nicht ändert und dass die meisten Teile es brauchen, die Antwort in diesem Sinne?Protokollierungsframework in Klassen injiziert werden

Antwort

3

Injection ist flexibler auf lange Sicht, da man leicht selektiv in bestimmten Orten injizieren und deaktivieren Sie die Protokollierung selektiv usw.

2

Ich denke, es mit Injektion es nichts falsch ist. Sie empfehlen, statische Variablen nur aus Leistungsgründen zu verwenden, aber ich sehe wenig Unterschied zwischen dieser und dem Einfügen eines Loggers beim Start.

1

Wenn die Speicherleistung nicht so ein Problem ist, könnten Sie AOP, z. mit PostSharp. Auf diese Weise müssen Ihre Klassen den Logger überhaupt nicht kennen. Sie injizieren IL-Code direkt in Ihre Assembly als Postbuild-Schritt. PostSharp verwendet Attribute zum Markieren von Methoden, Klassen und sogar ganzen Baugruppen. Es gibt sogar eine plugin für die Verwendung von log4net für das Problem der Protokollierung.

EDIT: Ich erwähnt Speicher, weil Sie mit jedem Attribut ein neues Objekt für jeden Join-Punkt erstellen.

+0

+1 für PostSharp, diese Scheiße ist magisch –

1

Obwohl Sie angegeben haben, dass sich die Protokollierung nicht ändern wird, schlage ich vor, von einem spezifischen Protokollierungsrahmen zu abstrahieren. Das Injizieren einer Logger-Instanz wird jedoch nicht in allen Fällen benötigt.

Nehmen Sie CommonLogging (siehe this Stackoverflow answer für eine kurze Beschreibung der Common.Logging ist) zum Beispiel: Ihre Klasse spricht direkt mit der Fabrik (LoggerManager), aber Sie sind nicht an eine bestimmte Logger-Implementierung gebunden.

0

Wenn Sie über Abhängigkeitsinjektion sprechen (sagen wir in der Spring.NET-Richtung), dann spielt es keine Rolle - obwohl Sie von mehreren Kopien von Logger-Instanzen nicht viel Wert erhalten. In der Regel ist jede Loggerinstanz, die von einem Framework mit einer bestimmten Klasse/einem bestimmten Namen zurückgegeben wird, ohnehin ein Singleton. Daher stellt sich die Frage, ob Sie jede Instanz mit einer Loggerreferenz und nicht mit einer einzelnen statischen Referenz pro Klasse durcheinander bringen möchten. Wenn Sie Bedenken haben, Loggerimplementierungen zu ändern, melden Sie sich an einer Schnittstelle an (CommonLogging, in einer anderen Antwort erwähnt, tut dies und unterstützt sowohl log4net- als auch Enterprise Library-Implementierungen).

Wenn Sie über Injektion mit AOP sprechen, dann bin ich mir nicht sicher, dass AOP-Injektion ab einem bestimmten Punkt flexibler ist. Sie sind ziemlich darauf beschränkt, Einträge, Exits und Exceptions mit Granularität auf Methodenebene zu protokollieren. AOP Injection ist eher ein Scatter-Shot-Ansatz, selbst wenn Sie AOP verwenden, um selektiv in Teile Ihres Codes zu injizieren. Obwohl das Logging als ein übergreifendes Anliegen der Art propagiert wird, das für AOP ideal ist, habe ich nie herausgefunden, dass AOP-basiertes Logging in der Praxis sehr nützlich ist (YMMV, natürlich).

0

CSharpAtl,

ich neugierig bin, wie genau Sie Log4net injizieren? Siehe meine Frage/Community Wiki here.

Ich sah auch Ihre Antwort auf eine DI/Log4net Frage here.

meisten Protokollierung Injektion Beispiele, die ich gesehen habe, zeigen eine Klasse eine „Logger“ injiziert, so etwas wie dies mit:

public class Foo 
{ 
    private ILogger logger; 

    public Foo(ILogger logger) //Injection via constructor 
    { 
    //Which "named" logger is this anyway? Is it Foo's? If so, how is it Foo's? 
    this.logger = logger; 
    } 

    public DoSomeWork(int xyz) 
    { 
    logger.Info("xyz = {0}", xyz); 
    } 
} 

Mit so etwas wie Log4net (und NLog, und vielleicht andere), erstellen Sie in der Regel ein Logger wie folgt aus:

public class Foo 
{ 
    private static ILogger logger = 
      LogManager.GetLogger(
       System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    public Foo() 
    { 
    } 

    public DoSomeWork(int xyz) 
    { 
    logger.Info("xyz = {0}", xyz); 
    } 
} 

Also, wie meine Klasse, Foo, die richtige Logger, wenn ich spritze Abhängigkeits? Vielleicht nenne ich meine Logger nicht streng nach der Klasse. Stattdessen könnte ich sie basierend auf einem Funktionsbereich (wie "DatabaseAccess", "AppStartup", "AppShutdown" usw.) benennen, die möglicherweise nicht vom Typ ableitbar sind.

Sie injizieren einen "Logger" (der einem benannten Logger entsprechen würde) oder einen "LogManager" (der dem LogManager von Log4net entsprechen würde), oder machen Sie etwas anderes? Verwenden Sie eine Konfigurationsfunktionalität einer DI-Plattform, um "benannte Instanzen" von injizierten Abhängigkeiten zuzuordnen? Ich denke, dass Unity so etwas unterstützt, obwohl ich mir nicht wirklich sicher bin.

Hier ist, wie ich könnte mir vorstellen, eine „LogManager“ Injektion funktionieren würde:

public class Foo 
{ 
    private static ILogger logger; 

    public Foo(ILogManager logManager) //Injection via constructor 
    { 
    logger = logManager.GetLogger 
        (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    //Since logger is (should it be?) static, maybe should be like this: 

    if (logger = null) 
    { 
     logManager.GetLogger 
       (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 
    } 
    } 

    public DoSomeWork(int xyz) 
    { 
    logger.Info("xyz = {0}", xyz); 
    } 
} 

Es scheint mir, dass wie ILogManager etwas Injektion (deren Umsetzung Log4net des LogManager wickeln würde) wäre einfacher als ILogger injectng , wegen der Frage, wie die DI-Plattform wissen würde, welcher ILogger injiziert werden soll.

Ich bin neu auf DI und .NET Logging-Plattformen (und eigentlich ziemlich neu in C# und .NET im Allgemeinen). Die überwiegende Mehrheit meiner Erfahrung in den letzten Jahren ist VB6 + VC++ 6.

Vielen Dank für jede Info ...

Begin bearbeiten ...

Ich habe auf SO einige mehr umsah und haben festgestellt, dass Sie auch nach AutoFac gefragt haben, also nehme ich an, dass Sie dies für Ihre DI verwenden. Wenn das wahr ist, dann denke ich, dass Sie auch etwas wie this oder, anscheinend noch besser, wie this tun, um Ihren Logger aufzulösen (nach Klassentyp). Ich schätze, das beantwortet die Frage, wie man zumindest in AutoFac benannte Logger (zB aus Log4Net oder NLog) einfügt.

Ende bearbeiten ...

Verwandte Themen