c# - unitycontainer - unity dependency injection
Cómo inyectar implementaciones de Log4Net ILog usando Unity 2.0 (6)
Con Unity 5 y superior, ahora puede usar la extensión Log4Net de Unity desde https://github.com/unitycontainer/log4net .
Todo lo que tienes que hacer es instalar el Nuget y agregar la extensión a tu contenedor:
container.AddNewExtension<Log4NetExtension>();
Y funcionará automáticamente con cualquier clase que use ILog
como una dependencia.
En última instancia, esto tiene que ver con la configuración de log4Net, pero en general, el problema no es el registro específico.
En general, lo que estoy tratando de averiguar es cómo hacer, en Microsoft Unity 2.0, algo equivalente a lo que uno obtiene con Castle.Facilities.Logging.LoggingFacility. Es decir, la capacidad de declarar una dependencia en un registrador y hacer que el registrador se inicialice con el Tipo del objeto en el que se está inyectando.
En el espíritu de una prueba vale más que mil palabras, esto es lo que necesito:
class Logger_IOC_Tests
{
//[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
/* Configuration Magic probably involiving registering either
* a custom IDependencyResolverPolicy or BuilderStrategy
* goes here...
*/
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
interface ILogger
{
Type GetUserType();
}
class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
public Type GetUserType()
{
return _type;
}
}
class LoggerUser
{
public readonly ILogger Logger;
public LoggerUser(ILogger logger)
{
Logger = logger;
}
}
Después de horas de investigar el código fuente de Unity, se me ocurrió la siguiente solución. Sin embargo, preferiría encontrar una manera de establecer la resolución de problemas adecuada en función del tipo que se resuelve en lugar de anular la política del selector de constructor predeterminado. Por un lado, porque anteriormente había anulado el selector de constructor predeterminado para otros propósitos. Por otro lado, esta solución solo maneja las dependencias que se inyectan a través del constructor. Supongo que para la cobertura total habría que anular la propiedad predeterminada y los selectores de métodos. Para mí, solo necesito constructores.
class Logger_IOC_Tests
{
[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
container.AddNewExtension<LoggingExtension>();
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
class LoggingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Policies.SetDefault(typeof(IConstructorSelectorPolicy), new LoggingConstructorSelectorPolicy());
}
}
public class LoggingConstructorSelectorPolicy : DefaultUnityConstructorSelectorPolicy
{
protected override IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
{
return parameter.ParameterType == typeof(ILogger)
? new LoggerResolverPolicy(parameter.Member.DeclaringType)
: base.CreateResolver(parameter);
}
}
class LoggerResolverPolicy : IDependencyResolverPolicy
{
private readonly Type _dependantType;
public LoggerResolverPolicy(Type dependantType)
{
_dependantType = dependantType;
}
public object Resolve(IBuilderContext context)
{
return new Logger(_dependantType);
}
}
He estado tratando de lograr el mismo resultado de poder insertar instancias ILog
configuradas correctamente en una dependencia utilizando la inyección de constructor con Unity.
Al final, escribí mi propia extensión de unidad "log4net" para hacer exactamente esto (en parte inspirada por una publicación del blog que escribió otro entrevistador, Kenneth Baltrinic).
Esto le permite registrar la extensión una vez con Unity:
var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
y luego pasar la instancia correcta del registrador ILog en:
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}
La extensión se puede encontrar aquí:
https://github.com/roblevine/UnityLoggingExtensions
Más información aquí: http://blog.roblevine.co.uk/net/using-log4net-with-unity/
EDITAR esto ahora está disponible como un paquete NuGet
La extensión anterior funciona bien, pero se necesita más información de configuración para los usuarios de MVC5. Aquí están los pasos usando la unidad.
Agregue la siguiente línea a la parte superior de su clase startup.cs sobre el espacio de nombres.
[ensamblaje: log4net.Config.XmlConfigurator (ConfigFile = "Web.config", Watch = true)]
En su método global.asax application_startup
agregue la siguiente información:
log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
El resto de la configuración al contenedor de la unidad debe ser como está:
container.AddNewExtension<Log4NetExtension>();
Asegúrate de tener un appender
agregado a tu web.config. Eso debería ser para que esto funcione correctamente. Buena suerte
No sé si esto es lo que está buscando, pero lo vi hace unos meses y lo recordé cuando vi su pregunta. No he usado Unity, así que no puedo comparar lo que has publicado con lo que está en el enlace. Esperemos que te sea de utilidad:
http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html
Puede usar el siguiente código para inyectar Log4Net
log4net.Config.BasicConfigurator.Configure();
container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));
Se utiliza typeof (Programa) ya que me estoy registrando en la clase del programa. El uso puede usar el nombre de la clase o esta palabra clave
Luego puedes inyectar ILog en la clase.
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}