Ich bin daran interessiert, mehr darüber zu erfahren, wie Benutzer die Protokollierung mit Abhängigkeitsinjektionsplattformen injizieren. Obwohl sich die folgenden Links und meine Beispiele auf log4net und Unity beziehen, werde ich keines davon unbedingt verwenden. Für die Abhängigkeitsinjektion / IOC werde ich wahrscheinlich MEF verwenden, da dies der Standard ist, auf den sich der Rest des Projekts (groß) einlässt.
Ich bin sehr neu in Dependency Injection / ioc und ziemlich neu in C # und .NET (habe nach den letzten 10 Jahren von VC6 und VB6 sehr wenig Produktionscode in C # /. NET geschrieben). Ich habe viele Untersuchungen zu den verschiedenen Protokollierungslösungen durchgeführt, die es gibt, daher denke ich, dass ich ihre Funktionen gut im Griff habe. Ich bin einfach nicht vertraut genug mit der tatsächlichen Mechanik, eine Abhängigkeit zu injizieren (oder, vielleicht "korrekter", eine abstrahierte Version einer Abhängigkeit zu injizieren).
Ich habe andere Beiträge im Zusammenhang mit Protokollierung und / oder Abhängigkeitsinjektion gesehen, wie: Abhängigkeitsinjektion und Protokollierungsschnittstellen
Best Practices für die Protokollierung
Wie würde eine Log4Net Wrapper-Klasse aussehen?
Nochmals zu log4net und Unity IOC config
Meine Frage hat nicht speziell mit "Wie injiziere ich die Protokollierungsplattform xxx mit dem ioc-Tool JJJ?" Zu tun. Ich bin vielmehr daran interessiert, wie die Leute mit dem Verpacken der Protokollierungsplattform (wie oft, aber nicht immer empfohlen) und der Konfiguration (dh app.config) umgegangen sind. Am Beispiel von log4net könnte ich beispielsweise (in app.config) eine Reihe von Loggern konfigurieren und diese Logger (ohne Abhängigkeitsinjektion) auf die Standardmethode für die Verwendung von Code wie folgt abrufen:
private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
Wenn mein Logger nicht nach einer Klasse, sondern nach einem Funktionsbereich benannt ist, kann ich alternativ Folgendes tun:
private static readonly ILog logger = LogManager.GetLogger("Login");
private static readonly ILog logger = LogManager.GetLogger("Query");
private static readonly ILog logger = LogManager.GetLogger("Report");
Ich denke also, dass meine "Anforderungen" ungefähr so aussehen würden:
Ich möchte die Quelle meines Produkts von einer direkten Abhängigkeit von einer Protokollierungsplattform isolieren.
Ich möchte in der Lage sein, eine bestimmte benannte Logger-Instanz (die wahrscheinlich dieselbe Instanz unter allen Anforderern derselben benannten Instanz gemeinsam nutzt) entweder direkt oder indirekt durch eine Art Abhängigkeitsinjektion, wahrscheinlich MEF, aufzulösen.
Ich weiß nicht, ob ich dies als harte Anforderung bezeichnen würde, aber ich möchte die Möglichkeit, bei Bedarf einen benannten Logger (anders als den Klassenlogger) zu erhalten. Zum Beispiel könnte ich einen Logger für meine Klasse basierend auf dem Klassennamen erstellen, aber eine Methode erfordert eine besonders umfangreiche Diagnose, die ich separat steuern möchte. Mit anderen Worten, ich möchte möglicherweise, dass eine einzelne Klasse von zwei separaten Logger-Instanzen "abhängt".
Beginnen wir mit Nummer 1. Ich habe eine Reihe von Artikeln gelesen, hauptsächlich hier über Stackoverflow, in denen es darum geht, ob es eine gute Idee ist, sie zu verpacken oder nicht. Sehen Sie sich den Link "Best Practices" oben an und lesen Sie den Kommentar von Jeffrey Hantin , um zu sehen, warum es schlecht ist, log4net zu verpacken. Wenn Sie wickeln würden (und wenn Sie effektiv wickeln könnten), würden Sie ausschließlich zum Zweck der Injektion / Entfernung der direkten Abhängigkeit wickeln? Oder würden Sie auch versuchen, einige oder alle Informationen der log4net app.config zu abstrahieren?
Angenommen, ich möchte System.Diagnostics verwenden. Ich möchte wahrscheinlich einen schnittstellenbasierten Logger implementieren (möglicherweise sogar die "gemeinsame" ILogger / ILog-Schnittstelle verwenden), wahrscheinlich basierend auf TraceSource, damit ich ihn injizieren kann. Würden Sie die Schnittstelle beispielsweise über TraceSource implementieren und einfach die System.Diagnostics app.config-Informationen unverändert verwenden?
Etwas wie das:
public class MyLogger : ILogger
{
private TraceSource ts;
public MyLogger(string name)
{
ts = new TraceSource(name);
}
public void ILogger.Log(string msg)
{
ts.TraceEvent(msg);
}
}
Und benutze es so:
private static readonly ILogger logger = new MyLogger("stackoverflow");
logger.Info("Hello world!")
Fahren Sie mit Nummer 2 fort ... Wie wird eine bestimmte benannte Logger-Instanz aufgelöst? Sollte ich nur die app.config-Informationen der von mir ausgewählten Protokollierungsplattform nutzen (dh die Logger basierend auf dem Namensschema in der app.config auflösen)? Könnte ich im Fall von log4net lieber LogManager "injizieren" (beachten Sie, dass ich weiß, dass dies nicht möglich ist, da es sich um ein statisches Objekt handelt)? Ich könnte LogManager umbrechen (MyLogManager nennen), ihm eine ILogManager-Schnittstelle geben und dann die MyLogManager.ILogManager-Schnittstelle auflösen. Meine anderen Objekte können eine Abhängigkeit (Import in MEF-Sprache) von ILogManager haben (Export aus der Assembly, in der sie implementiert sind). Jetzt könnte ich Objekte wie dieses haben:
public class MyClass
{
private ILogger logger;
public MyClass([Import(typeof(ILogManager))] logManager)
{
logger = logManager.GetLogger("MyClass");
}
}
Jedes Mal, wenn ILogManager aufgerufen wird, wird es direkt an den LogManager von log4net delegiert. Alternativ könnte der umschlossene LogManager die ILogger-Instanzen, die er basierend auf der app.config erhält, nehmen und sie dem (a?) MEF-Container nach Namen hinzufügen. Wenn später ein gleichnamiger Logger angefordert wird, wird der umschlossene LogManager nach diesem Namen abgefragt. Wenn der ILogger vorhanden ist, wird er auf diese Weise aufgelöst. Wenn dies mit MEF möglich ist, hat dies einen Vorteil?
In diesem Fall wird tatsächlich nur ILogManager "injiziert" und es können ILogger-Instanzen wie in log4net normalerweise ausgegeben werden. Wie ist diese Art der Injektion (im Wesentlichen einer Fabrik) mit der Injektion der genannten Logger-Instanzen zu vergleichen? Dies ermöglicht eine einfachere Nutzung der app.config-Datei von log4net (oder einer anderen Protokollierungsplattform).
Ich weiß, dass ich benannte Instanzen wie folgt aus dem MEF-Container abrufen kann:
var container = new CompositionContainer(<catalogs and other stuff>);
ILogger logger = container.GetExportedValue<ILogger>("ThisLogger");
Aber wie bekomme ich die genannten Instanzen in den Container? Ich kenne das Attribut-basierte Modell, bei dem ich verschiedene Implementierungen von ILogger haben könnte, von denen jede benannt ist (über ein MEF-Attribut), aber das hilft mir nicht wirklich. Gibt es eine Möglichkeit, so etwas wie eine app.config (oder einen Abschnitt darin) zu erstellen, in der die Logger (alle dieselbe Implementierung) nach Namen aufgelistet sind und die MEF lesen kann? Könnte / sollte es einen zentralen "Manager" (wie MyLogManager) geben, der benannte Logger über die zugrunde liegende app.config auflöst und dann den aufgelösten Logger in den MEF-Container einfügt? Auf diese Weise steht es einer anderen Person zur Verfügung, die Zugriff auf denselben MEF-Container hat (allerdings ohne das Wissen des MyLogManager über die Verwendung der app.config-Informationen von log4net).
Das ist schon ziemlich lange her. Ich hoffe es ist kohärent. Bitte teilen Sie uns spezifische Informationen darüber mit, wie Ihre Abhängigkeit eine Protokollierungsplattform (wir erwägen höchstwahrscheinlich log4net, NLog oder etwas (hoffentlich Dünnes), das auf System.Diagnostics basiert) in Ihre Anwendung eingefügt hat.
Haben Sie den "Manager" injiziert und ihn Logger-Instanzen zurückgeben lassen?
Haben Sie einige Ihrer eigenen Konfigurationsinformationen in Ihrem eigenen Konfigurationsabschnitt oder im Konfigurationsabschnitt Ihrer DI-Plattform hinzugefügt, um das direkte Injizieren von Logger-Instanzen zu vereinfachen (dh Ihre Abhängigkeiten sollten eher von ILogger als von ILogManager abhängen).
Wie wäre es mit einem statischen oder globalen Container, der entweder die ILogManager-Schnittstelle oder die Gruppe der benannten ILogger-Instanzen enthält? Anstatt im herkömmlichen Sinne (über Konstruktor-, Eigenschafts- oder Elementdaten) zu injizieren, wird die Protokollierungsabhängigkeit bei Bedarf explizit aufgelöst. Ist dies ein guter oder schlechter Weg, um Abhängigkeit zu injizieren.
Ich markiere dies als Community-Wiki, da es keine Frage mit einer eindeutigen Antwort zu sein scheint. Wenn sich jemand anders fühlt, können Sie dies jederzeit ändern.
Vielen Dank für jede Hilfe!
x.Request.ParentContext.Plan.Type.FullName
den konkreten Klassennamen anstelle des Schnittstellennamens erhalten.