Использование структуры map с оберткой log4net
У меня есть следующий интерфейс:
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...
}
Моя идея состояла в том, чтобы использовать structmap для создания экземпляра класса Log4netLogger с использованием типа класса, который выполнял ведение журнала. Тем не менее, я не могу на всю жизнь понять, как передать тип вызывающего класса структуре, чтобы он мог быть передан конструктору реализации журнала. Любые советы о том, как это сделать (или лучший способ), будут наиболее оценены.
Ответы
Ответ 1
Если параметр типа является контекстным, я не думаю, что это будет работать, как показано. Если вам нужно передать что-то конкретное в конструкторе, вам, скорее всего, придется создать интерфейс и реализацию factory, который возвращает экземпляр ILogger:
public interface ILoggerFactory
{
ILogger Create(Type type);
}
public class LoggerFactory : ILoggerFactory
{
public ILogger Create(Type type)
{
return new Log4netLogger(type);
}
}
Возможно, будет возможно загрузочная структура StructureMap, чтобы предоставить экземпляр, который вы хотите, на основе типа, но это предполагает ограниченное количество типов, которые вы знаете заранее.
Ответ 2
Мы используем аналогичную оболочку ILogger вокруг log4net и обычно используем инъекцию конструктора. Мы используем перехватчик как метод factory, ответственный за создание Регистратора. Вот наш типичный реестр для настройки ведения журнала.
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);
}
}
Нулевая проверка родительского типа необходима, если существуют зависимости от конкретных типов.
Остальное - необязательный файл настройки log4net.
Одна вещь, которая мне нравится в этой настройке, - это возможность использовать пустые регистраторы для модульного тестирования.
Ответ 3
Мне действительно нужно избавиться от привычки отвечать на свой вопрос, но для тех, кто сталкивается с ним, вот ответ.
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...");