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

C# 如何使用Unity 2.0注入Log4Net ILog实现,c#,dependency-injection,unity-container,log4net,castle-windsor,C#,Dependency Injection,Unity Container,Log4net,Castle Windsor,最终,这与设置log4Net有关,但一般来说,问题不是特定于日志 一般来说,我想弄清楚的是,在Microsoft Unity 2.0中,如何实现与Castle.Facility.Logging.LoggingFacility相当的功能。也就是说,能够声明对记录器的依赖关系,并使用注入记录器的对象的类型初始化记录器 本着“测试胜过千言万语”的精神,我需要的是: class Logger\u IOC\u测试 { //[测试] public void Logger\u应使用\u初始化\u使用\u it

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

一般来说,我想弄清楚的是,在Microsoft Unity 2.0中,如何实现与Castle.Facility.Logging.LoggingFacility相当的功能。也就是说,能够声明对记录器的依赖关系,并使用注入记录器的对象的类型初始化记录器

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

class Logger\u IOC\u测试
{
//[测试]
public void Logger\u应使用\u初始化\u使用\u it()的\u对象的\u类型\u
{
var container=new UnityContainer();
/*配置魔法可能也包括注册
*自定义idependencySolverPolicy或BuilderStrategy
*去这里。。。
*/
RegisterType(新的ContainerControlledLifetimeManager());
var user=container.Resolve();
Assert.True(user.Logger.GetUserType()==user.GetType());
}
}
接口ILogger
{
类型GetUserType();
}
类记录器:ILogger
{
私有只读类型_类型;
公共记录器(类型)
{
_类型=类型;
}
公共类型GetUserType()
{
返回型;
}
}
类记录器用户
{
公共只读ILogger记录器;
公共记录器用户(ILogger记录器)
{
记录器=记录器;
}
}

在对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);
    }
}
class Logger\u IOC\u测试
{
[测试]
public void Logger\u应使用\u初始化\u使用\u it()的\u对象的\u类型\u
{
var container=new UnityContainer();
container.AddNewExtension();
RegisterType(新的ContainerControlledLifetimeManager());
var user=container.Resolve();
Assert.True(user.Logger.GetUserType()==user.GetType());
}
}
类日志扩展:UnityContainerExtension
{
受保护的覆盖无效初始化()
{
SetDefault(typeof(IConstructorSelectorPolicy),new LoggingConstructorSelectorPolicy());
}
}
公共类日志构造函数SelectorPolicy:DefaultUnityConstructorSelectorPolicy
{
受保护的重写IDependencySolverPolicy CreateSolver(ParameterInfo参数)
{
return parameter.ParameterType==typeof(ILogger)
?新LoggerResolverPolicy(参数.Member.DeclaringType)
:base.CreateResolver(参数);
}
}
类LoggerResolverPolicy:IDependencyResolverPolicy
{
私有只读类型_依赖类型;
公共日志解析策略(类型相关类型)
{
_依亲类型=依亲类型;
}
公共对象解析(IBuilderContext上下文)
{
返回新的记录器(_类型);
}
}

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


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

最后,我写了自己的“log4net”unity扩展来实现这一点(部分灵感来自另一位回答者Kenneth Baltrinic写的博客文章)

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

var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
可在此处找到扩展名:

更多信息请点击此处:


编辑此功能现在以

的形式提供。上述扩展功能运行良好,但MVC5用户需要更多配置信息。下面是使用unity的步骤

在名称空间上方的startup.cs类顶部添加以下行

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

在global.asax
应用程序启动
方法中添加以下信息:

log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
unity容器的其余配置应如下所示:

container.AddNewExtension<Log4NetExtension>();
container.AddNewExtension();

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

有了Unity 5及以上版本,你现在可以从中使用Unity自己的Log4Net扩展

您只需安装Nuget并将扩展添加到容器中:

container.AddNewExtension<Log4NetExtension>();
container.AddNewExtension();

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

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

log4net.Config.BasicConfigurator.Configure();    

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

这一次你把锤子敲在头上了。这正是我想要的,比我的解决方案要好得多。非常感谢。为了它的价值,我从论坛和david的博客中收集了代码,并将它们放在我的博客上的一个地方。在Unity.codeplex讨论中有更高的抽象级别
LogCreation:UnityContainerExtension,其中U:ILogFactory,new()
。它将日志创建与日志框架分离。因此,可以对NLog使用相同的方法,例如,唯一的一件事是为特定的日志框架实现LogFactory。我已经结合了源代码,但我一辈子都无法阅读web.config log4net configurati
log4net.Config.BasicConfigurator.Configure();    

container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));
 public class MyClass
 {
   private readonly ILog logger;

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