2

Это будет длинный вопрос, но, пожалуйста, несите меня. Я пытаюсь создать компонент Logging для наших приложений, который может быть расширен для добавления новых фреймворков регистрации (NLog, Log4Net ec). Теперь я знаю, что у нас уже есть Common.Logging фасад, написанный Бен Фостером, но я хотел попробовать что-то более индивидуальное. Одним из основных требований в нашем случае является то, что нам нужен специальный механизм регистрации отдельных параметров/значений в базе данных с использованием структуры ведения журнала (в этом случае NLog). Таким образом, у меня есть простой интерфейс регистрации:Как получить имена журналов LogManager (NLog) с Unity

/// <summary> 
/// Interface for implementing a Logger Provider. 
/// </summary> 
public interface ILogger 
{ 
    /// <summary> 
    /// Logs an Info level diagnostics message. 
    /// </summary> 
    /// <param name="logInfo">The Log Info object.</param> 
    void Info(LogInfo logInfo); 

    /// <summary> 
    /// Logs a Warn level diagnostics message. 
    /// </summary> 
    /// <param name="logInfo">The Log Info object.</param> 
    void Warn(LogInfo logInfo); 

    /// <summary> 
    /// Logs a Debug level diagnostics message. 
    /// </summary> 
    /// <param name="logInfo">The Log Info object.</param> 
    void Debug(LogInfo logInfo); 

    /// <summary> 
    /// Logs an Error level diagnostics message. 
    /// </summary> 
    /// <param name="logInfo">The Log Info object.</param> 
    void Error(LogInfo logInfo); 

    /// <summary> 
    /// Logs an Fatal level diagnostics message. 
    /// </summary> 
    /// <param name="logInfo">The Log Info object.</param> 
    void Fatal(LogInfo logInfo); 
} 

Объект LogInfo содержит всю необходимую информацию для ведения журнала. У меня есть абстрактный класс, который реализует интерфейс:

public abstract class NLogLoggerBase : ILogger 
{ 
    .... 
} 

Который sublcassed в:

public class NLogDatabaseLogger : NLogLoggerBase 
{ 
    public NLogDatabaseLogger(ILogUtility logUtility) 
     : base(logUtility) 
    { 
     //Make sure the custom target is registered for use BEFORE using it. 
     ConfigurationItemFactory.Default.Targets.RegisterDefinition("DatabaseLog", typeof(DatabaseLogTarget)); 

     //initialize the _logger 
     _logger = LogManager.GetLogger("DatabaseLogger"); 
    } 
} 

и

public class NLogFileLogger : NLogLoggerBase 
{ 
    .... 
} 

базы данных регистратор использует пользовательский DatabaseTarget (который наследуется от TargetWithLayout в NLog) для входа в базу данных, а также для File Logger. Основные настройки для NLog подключены в App.Config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" /> 
    </configSections> 
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     autoReload="true" throwExceptions="false" internalLogFile="C:\Temp\nlog.txt" internalLogLevel="Info" 
     internalLogToConsole="false"> 
    <targets async="true"> 
     <target name="CustomDatabaseLog" xsi:type="DatabaseLog" /> 
     <target name="CustomFileLog" xsi:type="File" /> 
    </targets> 

    <rules> 
     <logger name="DatabaseLogger" minlevel="Info" writeTo="CustomDatabaseLog" /> 
     <logger name="FileLogger" minlevel="Info" writeTo="CustomFileLog" /> 
    </rules> 
    </nlog> 
</configuration> 

Пока все хорошо. У меня есть несколько тестов для каждого из регистраторов, и они регистрируются в соответствии с их целевыми показателями.

Тогда я написал Logger завод, который будет возвращать правильное применение интерфейса ILogger, на основе типа регистратора:

/// <summary> 
/// Provides an interface for a factory which returns a logger component. 
/// </summary> 
public interface ILoggerFactory 
{ 
    /// <summary> 
    /// Creates an instance of logger component based on dependency registration key. 
    /// </summary> 
    /// <param name="loggerName">The dependency registration key.</param> 
    /// <returns>An Instance of logger component.</returns> 
    ILogger CreateLogger(string loggerName); 
} 

и реализации:

/// <summary> 
/// Implementation of ILoggerFactory interface. 
/// </summary> 
public class NLogLoggerFactory : ILoggerFactory 
{ 
    private readonly ILogger _nlogDatabaseLogger; 
    private readonly ILogger _nlogFileLogger; 

    public NLogLoggerFactory(ILogger nlogDatabaseLogger, ILogger nlogFileLogger) 
    { 
     if (nlogDatabaseLogger == null) 
      throw new ArgumentNullException("nlogDatabaseLogger"); 

     if (nlogFileLogger == null) 
      throw new ArgumentNullException("nlogFileLogger"); 

     _nlogDatabaseLogger = nlogDatabaseLogger; 
     _nlogFileLogger = nlogFileLogger; 
    } 

    /// <summary> 
    /// Creates an instance of logger component based on dependency registration key. 
    /// </summary> 
    /// <param name="loggerKey">The dependency registration key.</param> 
    /// <returns>An Instance of logger component.</returns> 
    public ILogger CreateLogger(string loggerKey) 
    { 
     if (loggerKey.Equals(DependencyRegistrationKeys.NLogDatabaseLoggerKey)) 
      return _nlogDatabaseLogger; 

     if (loggerKey.Equals(DependencyRegistrationKeys.NLogFileLoggerKey)) 
      return _nlogFileLogger; 

     throw new ArgumentException("Invalid loggerKey"); 
    } 

Так я иду к проводке все это с Единством. Вот быстрый тест я залетела (я знаю, что нужно рефакторинга, но для иллюстративных целей):

[Test] 
    public void Test_if_logger_factory_returns_correct_implementation() 
    { 
     var container = new UnityContainer(); 
     container.RegisterType<ILogUtility, NLogUtility>(); 
     container.RegisterType<ILogger, NLogDatabaseLogger>(DependencyRegistrationKeys.NLogDatabaseLoggerKey); 
     container.RegisterType<ILogger, NLogFileLogger>(DependencyRegistrationKeys.NLogFileLoggerKey); 
     container.RegisterType<ILoggerFactory, NLogLoggerFactory>(
      new InjectionConstructor(
       new ResolvedParameter<ILogger>(DependencyRegistrationKeys.NLogDatabaseLoggerKey), 
       new ResolvedParameter<ILogger>(DependencyRegistrationKeys.NLogFileLoggerKey))); 

     var loggerFactory = container.Resolve<ILoggerFactory>(); 
     Assert.IsAssignableFrom<NLogLoggerFactory>(loggerFactory); 

     var logger = loggerFactory.CreateLogger(DependencyRegistrationKeys.NLogDatabaseLoggerKey); 
     Assert.IsNotNull(logger); 
     Assert.IsAssignableFrom<NLogDatabaseLogger>(logger); 
    } 

Все хорошо, пока я не попал в линию:

var loggerFactory = container.Resolve<ILoggerFactory>(); 

Это кажется ударить конструктор NLogDatabaseLogger, как и ожидалось, и взрывается на этой линии с исключением:

//initialize the _logger 
_logger = LogManager.GetLogger("DatabaseLogger"); 

исключение:

Required parameter 'FileName' on 'File Target[CustomFileLog_wrapped]' was not specified. 

Я предполагаю, что Unity борется с получением NLog, чтобы получить именованный экземпляр журнала. кто-нибудь сталкивался с этим раньше? Это что-то в этом роде? Я потратил все это время, стукнув головой об этом, но без кубиков. Любая помощь могла бы быть полезна!

+1

Где код для LogManager? Это от NLog? Я не думаю, что Unity является проблемой здесь, поскольку LogManager.GetLogger выглядит как вызов статического метода, NLogLoggerBase будет там, где нарушительный код находится в I reckon –

+0

True, LogManager - это статический класс, открытый NLog. Я закончил перемещение кода FileTarget в файл app.config – tranceporter

ответ

3

Проверьте этот вопрос и мой ответ.

How to Inject Log4Net ILog implementations using Unity 2.0

Речь идет о решении названных Log4Net лесорубов, используя единство, но я думаю, что вы должны быть в состоянии применить тот же процесс NLog и единство.

ОП этого вопроса написал nice blog post, в котором описана точная процедура, по которой он прошел, чтобы заставить это работать. Из его публикации в блоге это необходимые шаги (предполагает некоторое знание единства):

Реализация этого в Unity требует трех шагов.

  1. Создание Построить Tracking Extension
  2. Создание удлинительный Logger Создание
  3. Wire расширения в Unity

Удачи!

+0

Приветствия! У меня уже был LoggingUnityExtension, но я не знал, как использовать BuildStrategies. Я работаю сейчас, но если он перестанет работать снова, я добавил закладку в блог! – tranceporter

+0

Рад, что я могу помочь! – wageoghe