2009-08-24 17 views
5

He tropezado con algunas de estas preguntas en varios sitios y las respuestas parecen ser giradas por lnn officianados hacia el valor de la envoltura liviana que log4net 'es' (no ¿Lo entiendes?) y puntos similares de hecho alucinante.de nuevo sobre log4net y Unity IOC config

Sin embargo, parece que lo que los usuarios están pidiendo (y esta es mi pregunta) es cómo ajustar el modelo de objeto log4net en la secuencia registertype/registerinstance en la interfaz de configuración fluida.

El objetivo aquí no sería volver a ajustar l4n, sino simplemente tomar una referencia decente que no requiera secuestrar el flujo fluido, por así decirlo.

pobre flujo, quiero obtener una referencia a una instancia configurada de ILog de un método LogManger.GetLogger y ponerlo en el flujo fluido lo suficientemente temprano para inyectarlo en las propiedades de mis objetos de flujo descendente.

Así que en respuesta a una sugerencia de impaciencia, probé creado una instancia normal de ILOG en la forma canónica:

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

por lo que parece trivial (en el sentido real de esfuerzo) para añadir ahora que la referencia al contenedor de Unity y seguir con mi maravillosa vida.

Sin embargo, la firma del método RegisterInstance quiere un 'Tipo' no una interfaz.

Para aquellos que no han buscado a través del modelo de objetos log4net, los afficiananderos son correctos: l4n es un 'envoltorio' y no se puede obtener un holt del 'tipo' real para la cosa de registro.

Así que ahora tengo que probar. Y usted sabe lo que eso significa, podría tomar un minuto, pero lo más probable es que tome una hora o cuatro (similaridades como la ortografía de "hora" y "cuatro" nunca son una coincidencia en la vida real). trabajo

Sin embargo, lo que sigue, menos la parte elidida acerca de la configuración canónica, lo hicieron:

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

Así que los hashcodes para el objeto de registro original y el objeto de registro inyectados en la propiedad de mi pequeño objeto Context marvy Son identicos.

Sin embargo ...

El proceso de inyección requerida que expone la propiedad de registro del objeto de contexto a través de su interfaz, lo que significa que ya no podía ser un objeto estático. Y si el objeto Logognet ILog es estático parece ser el factor decisivo en cuanto a si es serializable y puede ser enmascarado entre ensamblajes sin las espectaculares advertencias "el tiempo de ejecución se volverá inestable" (que son realmente significativas solo para los fanáticos de Matrix).

Desalentada, aunque no disuadida, utilicé Resharper's ingenioso 'a la propiedad con un campo de respaldo' y establecí el campo de respaldo para que sea estático mientras que la propiedad Interfaz se mantuvo no estática. Bueno, se construyó y la prueba se ejecutó verde.

Así que incluso hice una reconstrucción y funcionó. Entonces, quizás cuando esto termine con las pruebas de integración, me escabulliré del log4net, no es una debacle serializable.

Así que tal vez esto ayudará

Gracias

Stato

+0

No es una práctica normal tener loggers como variables de instancia; normalmente son variables estáticas (es decir, de clase) y se implementan como singleton de todos modos. Por lo tanto, no creo que obtenga ningún beneficio al obtenerlos del contenedor de Unity. ¿Por qué lo necesita? –

+0

'¿por qué?' es definitivamente una pregunta razonable. La respuesta tiene que ver con un único punto de configuración. el uso de cualquier registrador 'en todas partes' llega a ser una carga de configuración real y el mantenimiento es pesado en la parte 'aint' cuando se trata de diversión. –

Respuesta

5

haría con el InjectionFactory en la Unidad 2 ayuda? (ver this question). Luego, su código de configuración sería algo como esto:

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

entonces recuperar el registrador con la llamada habitual de resolver():

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

También podría ser capaz de configurar el tiempo de vida del registrador ser ContainerControllerLifetimeManager también, para convertirlo en una instancia singleton, pero aún no lo he verificado.

+0

se parece a lo relacionado con log4net pero es útil para la instancia de objeto que también se compila para el inicio. Gracias. –

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

does indeed work.

Sin embargo, si tiene una propiedad para un registrador en una clase y desea inyectar esta instancia de registrador a ella, eso no funcionará AFAICT. Supongo que puedo estar fuera del objetivo, pero estoy intentando reutilizar la instancia del registrador en un nuevo contexto. Esto puede ser sólo puede deshacer, por lo que es posible que tenga que renunciar a su inyección y sólo tiene que añadir la línea

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

a todas las clases, que me da un resultado que sólo parece marginalmente diferente que instanciándola en cada clase .. ..

yo esperaba que

private ILog Logger {get;set;} 

solo podrían inyectarse, pero eso no parece funcionar en absoluto, ya que a lo largo de log4net todo se hace a través de interfaces y el registrador de hormigón se esconde detrás de la cortina con el mago de Oz.