Использование Structuremap с оболочкой log4net - PullRequest
10 голосов
/ 22 декабря 2009

У меня есть следующий интерфейс:

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 с использованием типа класса, который выполнял ведение журнала. Тем не менее, я не могу понять, как передать тип вызывающего класса в Structuremap, чтобы он мог быть передан конструктору реализации ведения журнала. Любой совет о том, как это сделать (или лучший способ), был бы очень признателен.

Ответы [ 3 ]

24 голосов
/ 28 декабря 2009

Мы используем аналогичную оболочку ILogger для log4net и обычно используем инжектор конструктора. Мы используем перехватчик как фабричный метод, отвечающий за создание 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);
    }
}

Проверка нулевого родительского типа необходима, когда есть зависимости от конкретных типов.

Остальное - необязательный параметр настройки log4net.

Одна вещь, которая мне нравится в этой настройке, это возможность использовать нулевые логгеры для модульного тестирования.

1 голос
/ 22 декабря 2009

Мне действительно нужно избавиться от привычки отвечать на свой вопрос, но для тех, кто сталкивается с ним, вот ответ.

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...");
1 голос
/ 22 декабря 2009

Если параметр типа зависит от контекста, я не думаю, что это будет работать так, как показано. Если вам нужно передать что-то специфическое для контекста в конструкторе, вам, вероятно, придется создать фабричный интерфейс и реализацию, которая возвращает экземпляр ILogger:

public interface ILoggerFactory
{
    ILogger Create(Type type);   
}

public class LoggerFactory : ILoggerFactory
{
    public ILogger Create(Type type)
    {
        return new Log4netLogger(type);
    }
}

Возможно, будет возможно загрузить StructureMap для предоставления нужного вам экземпляра на основе типа, но это предполагает ограниченное число типов, которые вы знаете заранее.

...