2011-12-20 15 views
5

Given ta klasa:Korzystanie LogManager.GetLogger z Jedności

class Foo 
{ 
    readonly ILog log; 

    public Foo(ILog log) 
    { 
     this.log = log; 
    } 

    ... 
} 

Chciałbym skonfigurować Jedności wstrzyknąć Ilog. To proste:

container.RegisterInstance<ILog>(LogManager.GetLogger(typeof(XYZ))); 

Ale chciałbym, aby wezwanie Unity LogManager.GetLogger z rodzajem dominującego typu rozwiązania.

To jest blisko:

container.RegisterType<ILog>(new InjectionFactory((c, t, s) => LogManager.GetLogger(t))); 

t Ale w tym przypadku jest typem jest rozwiązany (ILog), nie jest typem, że obiekt jest rozwiązany za (Foo).

wiem, że mogę to zrobić:

container.RegisterType<Foo>(new InjectionFactory(c => new Foo(LogManager.GetLogger(typeof(Foo))); 

Ale ja nie chcę dodać, że szalony każdą deklarację czas zarejestrować obiekt.

Wiem, że można to zrobić w Autofac i wiem, że Prawdziwa Odpowiedź nie ma w pierwszym rzędzie używać Jedności, ale czy można to zrobić? :)

Odpowiedz

6

Jedność może nie dać Ci wszystkich dodatków, które oferują inne pojemniki, ale jeszcze nie znalazłem funkcji, której nie można łatwo dodać.

var container = new UnityContainer(); 
container.AddNewExtension<TrackingExtension>(); 
container.RegisterType<ILog>(
    new InjectionFactory((ctr, type, name) => 
    { 
     var tracker = ctr.Resolve<ITracker>(); 
     var parentType = tracker.CurrentBuildNode.Parent.BuildKey.Type; 
     return LogManager.GetLogger(parentType); 
    })); 
var sut = container.Resolve<UsesLog>(); 
Assert.AreEqual(typeof(UsesLog), sut.Log.Type); 

można znaleźć kod źródłowy dla TrackingExtensionhere. Znajduje się on w folderze projektu TecX.Unity.

+0

dzięki, Skończyłem z czymś opartym na tym samym modelu. Jedną z rzeczy, którą odkryłem, było to, że musiałem wdrożyć IRecovery, aby obsłużyć przypadki, w których PostBuildUp nie został wywołany. –

+0

_PostBuildUp_ z _TrackingStrategy_ nie został wywołany? O ile mi wiadomo, jest to możliwe tylko wtedy, gdy strategia ogłosi kompilację jako kompletną w _PreBuildUp_ (której nie ma) lub jeśli w rurociągu znajduje się wyjątek, który przedwcześnie przerywa połączenie. –

+0

To prawda. Nie jestem pewien, czy były wyjątki, ale mamy pewne [Opcjonalne zależności], które mogą nie być możliwe do załadowania, więc nie ma nic do * PostBuildUp *. –

3

Jeśli chcesz, aby kontener DI zwrócił Ci program rejestrujący na podstawie informacji o klasie, wpisz informacje o typie do interfejsu publicznego, aby kontener DI mógł go zobaczyć. Usuwa wszelkie funkcje specyficzne dla kontenera, a wtedy nie ma znaczenia, czy używasz Unity czy AutoFac.

Ktoś który wie modelu obiektowego log4net dobrze może być w stanie podać bardziej efektywnego wdrożenia, ale spróbuj coś takiego:

using System; 
using Microsoft.Practices.Unity; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace UnityLoging 
{ 
    public interface ILog<T> : log4net.ILog 
    { } 

    public class MyLogger<T> : log4net.Core.LogImpl, ILog<T> 
    { 
     public MyLogger() : base(log4net.LogManager.GetLogger(typeof(T).Name).Logger) 
     { } 
    } 

    public class ClassToLog 
    { 
     private readonly log4net.ILog log; 

     public ClassToLog(ILog<ClassToLog> log) 
     { 
      this.log = log; 
     } 

     public void LogMe() 
     { 
      log.Debug("Got here"); 
     } 
    } 

    [TestClass] 
    public class TestClass 
    { 
     [TestMethod] 
     public void GenericLogRegistrationTest() 
     { 
      log4net.Config.XmlConfigurator.Configure(); 
      IUnityContainer container = new UnityContainer(); 
      container.RegisterType(typeof(ILog<>), typeof(MyLogger<>)); 

      ClassToLog c = container.Resolve<ClassToLog>(); 
      c.LogMe(); 

      log4net.LogManager.Shutdown(); 
     } 
    } 
} 
+0

Interesujące podejście. Jest to agnostyka kontenera, ale nieco gadatliwa, a programista musi wiedzieć, że _T_ w _ILog _ musi być zgodny z typem klasy, która ma logger jako zależność. –

Powiązane problemy