2

長文の質問になりますが、ご容赦ください。アプリケーション用の Logging コンポーネントを作成しようとしています。これは、プラグインの新しいロギング フレームワーク (NLog、Log4Net ec) に拡張できます。これで、Ben Foster によって記述された Common.Logging ファサードが既にあることがわかりましたが、もっとカスタマイズしたものを試してみたかったのです。この場合の主な要件の 1 つは、ロギング フレームワーク (この場合は 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 から継承) を使用してデータベースにログインし、ファイル ロガーも同様です。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>

ここまでは順調ですね。ロガーごとにいくつかのテストを行ったところ、それぞれのターゲットに問題なくログが記録されました。

次に、ロガー タイプに基づいて、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 を取得するのに苦労しています。誰もこれに遭遇したことがありますか?これを回避する方法はありますか?私はこれについて頭を叩いて午前中を過ごしましたが、サイコロはありません。どんな助けでも本当に感謝します!

4

1 に答える 1

3

この質問と私の答えを確認してください。

Unity 2.0 を使用して Log4Net ILog 実装を注入する方法

質問は、名前付きの log4net ロガーを unity を使用して解決することについてですが、同じプロセスを NLog と unity に適用できるはずだと思います。

その質問のOPは、これを機能させるために彼が行った正確な手順を説明する素晴らしいブログ投稿を書きました。彼のブログ投稿から、必要な手順は次のとおりです (unity についてある程度の知識があることを前提としています)。

これを Unity に実装するには、3 つの手順が必要です。

  1. ビルド追跡拡張機能の作成
  2. ロガー作成拡張機能の作成
  3. 拡張機能を Unity に接続する

幸運を!

于 2013-10-04T16:32:47.210 に答える