我有一个名为MyClass
的类,它使用两个名为Logger1
和Logger2
的不同记录器。我使用log4net进行日志记录,并希望将StructureMap用于DI。
如果没有StructureMap,我的课将如下所示:
public class MyClass
{
private static readonly ILog Logger1 = LogManager.GetLogger("Logger1"); // Loggers are configured in a config file
private static readonly ILog Logger2 = LogManager.GetLogger("Logger2");
public void DoSomething()
{
...
Logger1.Info("did something");
...
Logger2.Info("need to log this elsewhere");
}
}
使用StructureMap(使用v3.0.3)介绍DI,我将使loggers实例成员,并将它们注入构造函数,如下所示: 公共类MyClass { 私人只读ILog Logger1; 私人只读ILog Logger2;
myClass(ILog logger1, ILog logger2)
{
this.Logger1 = logger1;
this.Logger2 = logger2;
}
public void DoSomething()
{
...
Logger1.Info("did something");
...
Logger2.Info("need to log this elsewhere");
}
}
问题是,我无法让StructureMap为我正确连接。我尝试像这样连接记录器:
For<ILog>.Use(()=> LogManager.GetLogger("Logger1")).Named("Logger1");
For<ILog>.Use(()=> LogManager.GetLogger("Logger2")).Named("Logger2");
执行此操作获取空(未配置)记录器)。用Use()
替换Add()
会导致我的异常,因为没有为ILog注册默认实例。
有人知道我该怎么做吗?
答案 0 :(得分:4)
如果记录器执行不同的角色,那么我将创建两个继承自ILog的接口来反映这一点。这样,配置StructureMap来处理它们就没有问题了。
答案 1 :(得分:0)
我最终执行了以下操作:根据Rob的建议创建了两个界面:ILogger1
和ILogger2
。由于两者都具有相同的API,因为我需要相同的类功能,它们都从相同的接口继承 - 尽管不 log4net.ILog
按照史蒂文的建议:
interface IMyLog
{
void Info(object message);
void Info(string format, params object[] args);
}
interface ILogger1 : IMyLog { }
interface ILogger2 : IMyLog { }
此外,由于此API的实现与我的需求相同,因此我有一个具体的类MyLogger
,同时实现ILogger1
和ILogger2
。如果我需要实现不同,那么我将很容易有明确的接口实现或单独的类。只有My Logger
依赖于log4net,因为它将其用于实现:
enum LoggerType { Logger1, Logger2 }
internal class MyLogger : ILogger1, ILogger2
{
private readonly ILog _log;
public MyLogger(LoggerType loggerName)
{
switch (loggerName)
{
case LoggerType.Logger1:
_log = LogManager.GetLogger("first-log");
break;
case LoggerType.Logger2:
_log = LogManager.GetLogger("second-log");
break;
default:
throw new ArgumentException("Invalid logger name", "loggerName");
}
}
public void Info(object message)
{
_log.Info(message);
}
public void Info(string format, params object[] args)
{
_log.InfoFormat(format, args);
}
}
为了使用 StructureMap 注册它,我在注册表中使用了以下代码:
For<ILogger1>().Use<MyLogger>().Ctor<LoggerType>("loggerName").Is(LoggerType.Logger1).Singleton(); // I want only one logger per type
For<ILogger2>().Use<MyLogger>().Ctor<LoggerType>("loggerName").Is(LoggerType.Logger2).Singleton();
这一切都很有效。所以,感谢Steven和Rob的建议。我真的学到了点东西。我希望我能不止一次地回答答案和答复。
总而言之,我:
答案 2 :(得分:0)
作为上述答案的替代,这可以仅在StructureMap中解决(我相信适用于问题中使用的SM版本)。您可以通过在注册表中包含以下内容来告诉StructureMap如何构建MyClass
。
For<MyClass>().Use(x => new MyClass(x.GetInstance<ILog>("Logger1"), x.GetInstance<ILog>("Logger2")));