如何使用Unity 2.0注入Log4Net ILog实现

本文关键字:Log4Net ILog 实现 注入 何使用 Unity | 更新日期: 2023-09-27 18:03:56

最终,这与设置log4Net有关,但一般来说,问题不是特定于日志记录的。

一般来说,我想弄清楚的是,在Microsoft Unity 2.0中,如何做一些与Castle.Facilities.Logging.LoggingFacility等效的事情。也就是说,能够声明对记录器的依赖关系,并用要注入的对象的类型初始化记录器。

本着测试胜过千言万语的精神,以下是我需要的:

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

如何使用Unity 2.0注入Log4Net ILog实现

我不知道这是否是你想要的,但我几个月前看到了它,当我看到你的问题时,我想起了它。我没有使用Unity,所以我真的无法将你发布的内容与链接上的内容进行比较。希望它对你有用:

http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html

我一直在尝试实现相同的结果,即能够使用Unity的构造函数注入将正确配置的ILog实例插入到依赖项中。

最后,我写了自己的"log4net"统一扩展来做到这一点(部分灵感来自另一位回答者Kenneth Baltrinic写的一篇博客文章(。

这允许您向Unity:注册一次扩展

var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();

然后传入正确的ILog记录器实例:

public class MyClass
{
    private readonly ILog logger;
    public MyClass(ILog logger)
    {
        this.logger = logger;
    }
}

扩展可以在这里找到:

https://github.com/roblevine/UnityLoggingExtensions

更多信息请点击此处:http://blog.roblevine.co.uk/net/using-log4net-with-unity/

EDIT现在可以作为NuGet包使用

在对Unity源代码进行了数小时的挖掘之后,我提出了以下解决方案。但是,我更愿意找到一种方法,根据要解析的类型设置适当的依赖关系解析程序,而不是重写默认的构造函数选择器策略。首先,因为我之前为了其他目的重写了默认的构造函数选择器。另一方面,这个解决方案只处理通过构造函数注入的依赖项。对于完全覆盖,我认为也必须覆盖默认的属性和方法选择器。就我自己而言,我只需要构造函数。

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

上述扩展运行良好,但MVC5用户需要更多配置信息。以下是使用统一的步骤。

将以下行添加到命名空间上方startup.cs类的顶部。

[程序集:log4net.Config.XmlConfigurator(ConfigFile="Web.Config",Watch=true(]

在global.asax application_startup方法中添加以下信息:

log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));

统一容器的其余配置应如下所示:

container.AddNewExtension<Log4NetExtension>();

请确保在web.config中添加了一个appender。这样就可以正常工作了。好运

使用Unity 5及以上版本,您现在可以使用Unity自己的Log4Net扩展https://github.com/unitycontainer/log4net.

你所要做的就是安装Nuget并将扩展添加到你的容器中:

container.AddNewExtension<Log4NetExtension>();

它将自动处理任何使用ILog作为依赖项的类。

您可以使用以下代码注入Log4Net

log4net.Config.BasicConfigurator.Configure();    
container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));

typeof(程序(是使用的,因为我正在程序类中注册。使用可以使用类名或这个关键字

然后可以将ILog注入类

 public class MyClass
 {
   private readonly ILog logger;
   public MyClass(ILog logger)
   {
     this.logger = logger;
   }
 }