Log4net 将LogManager.GetLogger与Unity一起使用
鉴于这一类别:Log4net 将LogManager.GetLogger与Unity一起使用,log4net,unity-container,Log4net,Unity Container,鉴于这一类别: class Foo { readonly ILog log; public Foo(ILog log) { this.log = log; } ... } 我想将Unity配置为注入ILog。这很简单: container.RegisterInstance<ILog>(LogManager.GetLogger(typeof(XYZ))); 但是在这种情况下,t是要解析的类型(ILog),而不是对象解析的
class Foo
{
readonly ILog log;
public Foo(ILog log)
{
this.log = log;
}
...
}
我想将Unity配置为注入ILog。这很简单:
container.RegisterInstance<ILog>(LogManager.GetLogger(typeof(XYZ)));
但是在这种情况下,t
是要解析的类型(ILog
),而不是对象解析的类型(Foo
)
我知道我能做到:
container.RegisterType<Foo>(new InjectionFactory(c => new Foo(LogManager.GetLogger(typeof(Foo)));
container.RegisterType(新注入工厂(c=>newfoo(LogManager.GetLogger(typeof(Foo)));
但我不想每次注册一个对象时都要添加那个疯狂的声明
我知道这可以在Autofac中实现,我知道真正的答案是首先不使用Unity,但这可以实现吗?:)Unity可能无法提供其他容器提供的所有功能,但我还没有找到一个您无法轻松添加的功能。
var container=newunitycontainer();
container.AddNewExtension();
container.RegisterType(
新注入工厂((中心、类型、名称)=>
{
var tracker=ctr.Resolve();
var parentType=tracker.CurrentBuildNode.Parent.BuildKey.Type;
返回LogManager.GetLogger(parentType);
}));
var sut=container.Resolve();
AreEqual(typeof(UsesLog),sut.Log.Type);
您可以找到TrackingExtension的源代码。它位于TecX.Unity项目文件夹中。如果您希望DI容器根据类的类型信息返回记录器,则将类型信息放入公共接口,以便DI容器可以看到它。这样就不需要任何特定于容器的覆盖然后,无论您使用的是Unity还是AutoFac,这都无关紧要 熟悉log4net对象模型的人可能会为您提供更高效的实现,但请尝试以下方法:
using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnityLoging
{
public interface ILog<T> : log4net.ILog
{ }
public class MyLogger<T> : log4net.Core.LogImpl, ILog<T>
{
public MyLogger() : base(log4net.LogManager.GetLogger(typeof(T).Name).Logger)
{ }
}
public class ClassToLog
{
private readonly log4net.ILog log;
public ClassToLog(ILog<ClassToLog> log)
{
this.log = log;
}
public void LogMe()
{
log.Debug("Got here");
}
}
[TestClass]
public class TestClass
{
[TestMethod]
public void GenericLogRegistrationTest()
{
log4net.Config.XmlConfigurator.Configure();
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(ILog<>), typeof(MyLogger<>));
ClassToLog c = container.Resolve<ClassToLog>();
c.LogMe();
log4net.LogManager.Shutdown();
}
}
}
使用系统;
使用Microsoft.Practices.Unity;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
命名空间单元化
{
公共接口ILog:log4net.ILog
{ }
公共类MyLogger:log4net.Core.LogImpl,ILog
{
public MyLogger():base(log4net.LogManager.GetLogger(typeof(T).Name).Logger)
{ }
}
公共类类日志
{
私有只读log4net.ILog日志;
公共类日志(ILog日志)
{
this.log=log;
}
公共无效日志()
{
调试(“到达这里”);
}
}
[测试类]
公共类TestClass
{
[测试方法]
公共无效GenericLogRegistrationTest()
{
log4net.Config.XmlConfigurator.Configure();
IUnityContainer容器=新的UnityContainer();
RegisterType(typeof(ILog),typeof(MyLogger));
ClassToLog c=container.Resolve();
c、 LogMe();
log4net.LogManager.Shutdown();
}
}
}
这似乎是一个非常干净的方法:谢谢,我最终使用了基于相同模型的东西。我发现一件事是我必须实现IRecovery来处理未调用PostBuilding的情况。TrackingStrategy的PostBuilding没有被调用?据我所知,只有在策略声明没有调用的情况下,这才有可能他认为在预构建中构建是完整的(事实并非如此),或者管道中的某个地方存在异常,从而过早地中断了链。没错。我不确定是否存在异常,但我们确实存在一些[可选依赖性]这可能无法加载,因此不需要进行后期构建。有趣的方法。它与容器无关,但有点冗长,开发人员需要知道ILog中的T必须与将记录器作为依赖项的类的类型匹配。
var container = new UnityContainer();
container.AddNewExtension<TrackingExtension>();
container.RegisterType<ILog>(
new InjectionFactory((ctr, type, name) =>
{
var tracker = ctr.Resolve<ITracker>();
var parentType = tracker.CurrentBuildNode.Parent.BuildKey.Type;
return LogManager.GetLogger(parentType);
}));
var sut = container.Resolve<UsesLog>();
Assert.AreEqual(typeof(UsesLog), sut.Log.Type);
using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnityLoging
{
public interface ILog<T> : log4net.ILog
{ }
public class MyLogger<T> : log4net.Core.LogImpl, ILog<T>
{
public MyLogger() : base(log4net.LogManager.GetLogger(typeof(T).Name).Logger)
{ }
}
public class ClassToLog
{
private readonly log4net.ILog log;
public ClassToLog(ILog<ClassToLog> log)
{
this.log = log;
}
public void LogMe()
{
log.Debug("Got here");
}
}
[TestClass]
public class TestClass
{
[TestMethod]
public void GenericLogRegistrationTest()
{
log4net.Config.XmlConfigurator.Configure();
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(ILog<>), typeof(MyLogger<>));
ClassToLog c = container.Resolve<ClassToLog>();
c.LogMe();
log4net.LogManager.Shutdown();
}
}
}