2011-12-20 10 views
5

Dada esta clase:LogManager.GetLogger con Unity

class Foo 
{ 
    readonly ILog log; 

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

    ... 
} 

Me gustaría configurar la unidad para inyectar ILOG. Eso es fácil:

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

pero me gustaría hacer una llamada Unidad LogManager.GetLogger con el tipo del tipo padre en vías de solución.

Esto está cerca:

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

Pero t en este caso es del tipo resolverse (ILog), no es el tipo que el objeto se resuelve por (Foo).

Sé que puedo hacer esto:

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

pero no quiero tener que añadir que la declaración loca cada vez que registre un objeto.

Sé que esto se puede hacer en Autofac, y sé que la verdadera respuesta es no utilizar Unity en primer lugar, pero ¿se puede hacer esto? :)

Respuesta

6

Unity podría no darle todas las cosas buenas que ofrecen algunos de los otros contenedores, pero aún no he encontrado una función que no pueda agregar fácilmente.

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

Puede encontrar el código fuente para el TrackingExtensionhere. Está ubicado en la carpeta del proyecto TecX.Unity.

+0

Gracias, Terminé yendo con algo basado en el mismo modelo. Una cosa que encontré es que tuve que implementar IRecovery para manejar casos donde no se llamó a PostBuildUp. –

+0

_PostBuildUp_ de _TrackingStrategy_ no se llamó? Hasta donde sé, esto solo es posible si la estrategia declara que la compilación está completa en _PreBuildUp_ (que no) o si hay una excepción en algún lugar de la interconexión que interrumpe prematuramente la cadena. –

+0

eso es correcto. No estoy seguro de si hubo excepciones, pero tenemos algunas [OptionalDependencies] que podrían no cargarse, por lo que no hay nada para * PostBuildUp *. –

3

Si desea que un contenedor DI le devuelva un registrador basado en la información del tipo de clase, coloque la información del tipo en la interfaz pública para que el contenedor DI pueda verla. Elimina la necesidad de funciones de anulación específicas del contenedor y, a continuación, no importará si está utilizando Unity o AutoFac.

Alguien que conoce bien el modelo de objetos log4net podría ser capaz de darle una aplicación más eficiente, pero intentar algo como esto:

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

Enfoque interesante. Es independiente del contenedor pero un poco detallado y un desarrollador necesita saber que el _T_ en _ILog _ debe coincidir con el tipo de la clase que tiene el registrador como una dependencia. –