簡體   English   中英

如何使用Unity為LogManager(NLog)獲取命名記錄器

[英]How to get named loggers for LogManager (NLog) with Unity

這將是一個漫長的問題,但是請忍受我。 我正在嘗試為我們的應用程序創建一個日志記錄組件,該組件可以擴展為插入新的日志記錄框架(NLog,Log4Net ec)。 現在我知道我們已經有了Ben Foster編寫的Common.Logging門面,但是我想嘗試一些更定制的東西。 在我們的案例中,主要要求之一是,我們需要一種使用日志記錄框架(在這種情況下為NLog)將自定義參數/值記錄到數據庫的自定義機制。 所以我有一個簡單的日志記錄界面:

/// <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
{
     ....
}

歸類為:

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(從NLog中的TargetWithLayout繼承)登錄數據庫,並使用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");
    }

因此,我將使用Unity進行所有連接。 這是我提出的快速測試案例(我知道它需要重構,但這只是出於說明目的):

    [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來獲取命名記錄器實例。 有人遇到過嗎? 有沒有辦法解決? 我整個上午都在為此事而,但沒有骰子。 任何幫助將非常感激!

看看這個問題和我的答案。

如何使用Unity 2.0注入Log4Net ILog實現

問題是關於使用unity解決命名的log​​4net記錄器,但是我認為您應該能夠對NLog和unity應用相同的過程。

該問題的操作人員撰寫了一篇不錯的博客文章,描述了他為使此功能生效所經過的確切過程。 在他的博客文章中,這些是必需的步驟(假設有一些統一的知識):

在Unity中實現此過程需要三個步驟。

  1. 創建構建跟蹤擴展
  2. 創建記錄器創建擴展
  3. 將擴展連接到Unity

祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM