我有以下界面:
public interface ILogger
{
void Debug(string message, params object[] values);
void Info(string message, params object[] values);
void Warn(string message, params object[] values);
void Error(string message, params object[] values);
void Fatal(string message, params object[] values);
}
以及以下实施:
public class Log4netLogger : ILogger
{
private ILog _log;
public Log4netLogger(Type type)
{
_log = LogManager.GetLogger(type);
}
public void Debug(string message, params object[] values)
{
_log.DebugFormat(message, values);
}
// other logging methods here...
}
我的想法是使用结构图来实例化 Log4netLogger 类,并使用执行日志记录的类的类型。但是,我一生都无法弄清楚如何将调用类的类型传递给 Structuremap,以便将其传递给日志记录实现的构造函数。任何有关如何做到这一点(或更好的方法)的建议将不胜感激。
我们在 log4net 周围使用类似的 ILogger 包装器,并且通常使用构造函数注入。我们使用拦截器作为负责创建 Logger 的工厂方法。这是我们用于日志记录设置的典型注册表。
public class CommonsRegistry : Registry
{
public CommonsRegistry()
{
For<ILogger>()
.AlwaysUnique()
.TheDefault.Is.ConstructedBy(s =>
{
if (s.ParentType == null)
return new Log4NetLogger(s.BuildStack.Current.ConcreteType);
return new Log4NetLogger(s.ParentType);
});
var applicationPath = Path.GetDirectoryName(Assembly.GetAssembly(GetType()).Location);
var configFile = new FileInfo(Path.Combine(applicationPath, "log4net.config"));
XmlConfigurator.ConfigureAndWatch(configFile);
}
}
当存在对具体类型的依赖时,父类型 null 检查是必要的。
其余的是可选的 log4net 设置内容。
我喜欢这个设置的一件事是能够使用空记录器进行单元测试。
如果类型参数是特定于上下文的,我认为这不会像所示的那样工作。如果您需要在构造函数中传递特定于上下文的内容,则可能必须创建一个工厂接口和实现来返回 ILogger 的实例:
public interface ILoggerFactory
{
ILogger Create(Type type);
}
public class LoggerFactory : ILoggerFactory
{
public ILogger Create(Type type)
{
return new Log4netLogger(type);
}
}
也许可以引导 StructureMap 根据类型提供您想要的实例,但这假设您事先知道的类型数量有限。
我真的需要改掉回答自己问题的习惯,但对于那些遇到这个问题的人来说,这就是答案。
return ObjectFactory.With(type).GetInstance<T>();
我实际上有一个结构映射的包装器(以避免将结构映射依赖项暴露给我的应用程序),如下所示:
public static class ServiceManager
{
public static T Get<T>()
{
return ObjectFactory.GetInstance<T>();
}
public static T Get<T>(Type type)
{
return ObjectFactory.With(type).GetInstance<T>();
}
}
代码中任何时候我需要记录器,我都会调用以下内容:
ServiceManager.Get<ILogger>(GetType()).Info("Logging page view...");