2009-08-24 9 views
5

Ich habe ein paar dieser Fragen über verschiedene Websites gestoßen und die Antworten scheinen von l4n officianados in Richtung der Wert der leichten Wrapper, die log4net "ist" (nicht Sie bekommen es?) und ähnliche Punkte der verwirrenden Tatsache.wieder über log4net und Unity IOC config

Es scheint jedoch, dass die Benutzer fragen (und das ist meine Frage) ist, wie Sie das Log4net Objet-Modell in die registertype/registerinstance Sequenz in der fließend Config-Schnittstelle passen.

Das Ziel hier wäre nicht wieder zu wickeln l4n, sondern einfach eine anständige Referenz zu greifen, die nicht unbedingt den fließenden Fluss entführen muss, sozusagen.

Ich möchte einen Verweis auf eine konfigurierte Instanz von ILog von einer LogManger.GetLogger-Methode abrufen und es früh genug in den fließenden Fluss einfügen, um es in Eigenschaften meiner Downstream-Objekte zu injizieren.

So in Reaktion auf einen ungeduldig Vorschlag habe ich versucht, erstellt eine normale Instanz ILog in der kanonischen Weise:

log4net.Config.XmlConfigurator.Configure(); 
static readonly log4Net.Ilog Log = LogManager.GetLogger(thatlongassemblyreflectionstuff); 

So wäre es trivial erscheinen (im wahrsten Sinne des ermüdungs) nun, dass der Bezug hinzufügen in den Container der Einheit und mach weiter mit meinem wunderbaren Leben.

Die Signatur für die RegisterInstance-Methode möchte jedoch einen "Typ", keine Schnittstelle.

Für diejenigen, die das log4net-Objektmodell nicht durchsucht haben, sind die afficianander korrekt: l4n ist ein "Wrapper" und Sie können keinen Holt des tatsächlichen "type" für das Log-Ding bekommen.

Also jetzt muss ich testen. Und Sie wissen, was das bedeutet, es könnte eine Minute dauern, wird aber wahrscheinlich eine Stunde oder vier dauern (Ähnlichkeiten wie die Schreibweise von "Stunde" und "Vier" sind im wirklichen Leben nie zufällig).

jedoch die folgenden, minus der elided Teil über die kanonische Setup funktioniert:

container 
    .RegisterInstance("Logger", Log, new ContainerControlledLifetimeManager()) 
.RegisterType<IControllerContext, ControllerContext> 
(
    "CtlrCtx", 
    new ContainerControlledLifetimeManager(), 
    new InjectionConstructor(new ResolvedParameter<IMessageBuilder>("MsgBldr")), 
    new InjectionProperty("Log",new ResolvedParameter<ILog>("Logger")) 
); 

So ist die Hashcodes für das ursprüngliche Log-Objekt und das Log-Objekt in das Eigentum meines marvy wenig Context Objekts injizierten sind identisch.

jedoch ...

Der Einspritzvorgang erforderlich, dass ich die Log-Eigenschaft des Context-Objekt über seine Schnittstelle aussetzen, es nicht mehr könnte ein statisches Objekt Bedeutung sein. Und ob das log4net-ILog-Objekt statisch ist, scheint der entscheidende Faktor dafür zu sein, ob es serialisierbar ist und zwischen Assemblierungen angeordnet werden kann, ohne dass die Warnungen "die Laufzeit wird instabil werden" wirklich nur für Matrix-Fans von Bedeutung sind.

Entmutigt, obwohl nicht abgeschreckt, ich verwendet Resharper's raffiniert 'zu Eigenschaft mit einem Hintergrundfeld' und setzen Sie das Hintergrundfeld statisch, während die Eigenschaft Interface nicht statisch blieb. Gut gebaut und der Test lief grün.

Also habe ich sogar einen Umbau und es hat funktioniert. Also, wenn es zu den Integrationstests kommt, schleiche ich mich an dem log4net vorbei, ist kein serialisierbares Debakel.

Vielleicht wird dies dazu beitragen

Dank

Stato

+0

Es ist nicht üblich Logger als Instanzvariablen zu verwenden - sie sind normalerweise statische (d. H. Klassen) Variablen und werden trotzdem als Singletons implementiert. Ich denke also nicht, dass Sie einen Vorteil daraus ziehen können, wenn Sie sie aus dem Unity-Container holen. Warum brauchen Sie das? –

+0

Warum? ist definitiv eine vernünftige Frage. Die Antwort hat mit einem einzigen Konfigurationspunkt zu tun. mit jedem Logger "überall" wird eine echte Konfigurationslast und Wartung ist schwer auf der "Aint" Teil, wenn es um Spaß geht. –

Antwort

5

würde die InjectionFactory in Unity 2 Hilfe bei der Verwendung? (siehe this question). Dann würde Ihr Konfigurationscode wie folgt aussehen:

IUnityContainer container = new UnityContainer(); 
container.RegisterType<ILog>(new InjectionFactory(factory => LogManager.GetLogger())); 

Dann holen Sie den Logger mit dem üblichen Aufruf Resolve():

ILog logger = container.Resolve<ILog>(); 
logger.Log(Level.Debug, "Hello world"); 

Sie könnten auch in der Lage sein, um die Lebensdauer des Loggers zu konfigurieren auch ContainerControllerLifetimeManager, um es zu einer Singleton-Instanz zu machen, aber das habe ich noch nicht verifiziert.

+0

sieht wie log4net aus, ist aber nützlich für Objektinstanzen, die auch für den Start erstellt werden. Vielen Dank. –

0
ILog logger = container.Resolve<ILog>(); 
logger.Log(Level.Debug, "Hello world"); 

funktioniert tatsächlich.

Wenn Sie jedoch eine Eigenschaft für einen Logger in einer Klasse haben und diese Logger-Instanz in diese Klasse injizieren möchten, funktioniert AFAICT nicht. Ich vermute, dass ich nicht im Ziel bin, aber ich versuche, die Logger-Instanz in einem neuen Kontext wiederzuverwenden. Dies kann nur rückgängig gemacht werden, so dass ich es aufgeben müssen möglicherweise auf die Injektion und fügen Sie einfach die Linie

ILog logger = container.Resolve<ILog>(); 

zu jeder Klasse, die mir ein Ergebnis gibt, die nur geringfügig anders scheint, als es in jeder Klasse instanziieren .. ..

ich hatte gehofft, dass

private ILog Logger {get;set;} 

nur injiziert werden könnte, aber das scheint nicht überhaupt, zu arbeiten, da alle durch log4net alles über Schnittstellen erfolgt und die Beton Logger hinter dem Vorhang versteckt mit dem Zauberer von Oz.

Verwandte Themen