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

时间:2011-07-27 14:46:08

标签: c# dependency-injection unity-container log4net castle-windsor

最终这与设置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;
    }
}

6 个答案:

答案 0 :(得分:14)

我不知道你是否正在寻找这个,但几个月前我就看到它了,当我看到你的问题时,它被提醒了。我没有使用Unity,所以我无法真正比​​较你发布的内容和链接中的内容。希望它对您有用:

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

答案 1 :(得分:9)

我一直在努力实现与使用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/

编辑现在可以NuGet package

的形式使用

答案 2 :(得分:4)

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

答案 3 :(得分:2)

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

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

  

[assembly:log4net.Config.XmlConfigurator(ConfigFile =&#34; Web.config&#34;,Watch = true)]

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

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

统一容器的其余配置应该是:

container.AddNewExtension<Log4NetExtension>();

确保您的web.config中添加了appender。这应该是为了让它正常工作。祝你好运

答案 4 :(得分:1)

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

所有您需要做的就是安装Nuget并将扩展名添加到您的容器中

container.AddNewExtension<Log4NetExtension>();

并且它将自动与任何将ILog用作依赖项的类一起使用。

答案 5 :(得分:0)

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

log4net.Config.BasicConfigurator.Configure();    

container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));
由于我正在程序类中注册,因此使用

typeof(Program)。使用可以使用类名或此关键字

然后您可以将ILog注入到类中

 public class MyClass
 {
   private readonly ILog logger;

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