12

Visual Studio 2012 の私のソリューションには、現在 2 つのプロジェクトが含まれています。

  • DLL
  • WPF アプリケーション (DLL のメソッドが必要)

DLL と WPF アプリケーションの両方NLogがログに使用します。現在、各プロジェクトにはNLogDLL 自体が含まれています。

ここに私が理解していないものがあります:

  1. NLog各プロジェクトに同一の DLLを含める必要はないように思われます。
  2. ただし、DLL は他のソリューションで再利用できる必要があります。つまり、何らかの方法でNLogDLL を DLL プロジェクトに含める必要があります。

Visual Studio ソリューションやプロジェクトをセットアップする適切な方法は何ですか?

4

3 に答える 3

9

それを使用するすべてのプロジェクトでDLLが必要であり、実行時に見つけて使用できるように、実行可能ファイル(あなたの場合はWPFアプリケーション)のバイナリで展開する必要があります。

私がすべてのプロジェクトで行う傾向があるのは、Log4Net や NLog などの特定のサード パーティのログ API を参照して依存する必要がないように、ログ エンジンの周りにラッパーを作成することです。ラッパー クラスのプロジェクトと実行可能プロジェクトでのみログ アセンブリへの参照を持ち、アセンブリを bin フォルダーにデプロイします。

お役に立てれば ;-)

于 2013-03-12T08:45:21.293 に答える
8

DLL が、さまざまなプロジェクト間で共有することを計画している単なるコア ライブラリである場合は、そのライブラリだけに NLog 参照​​とラッパー コードを追加し、コンシューマー アプリケーション (WPF プロジェクトなど) に NLog があることを確認するのが賢明な場合があります。それに関連付けられている .config ファイル。

VS2012 を使用しているので、新しい呼び出し元情報属性を利用できる .NET 4.5 を使用している可能性が最も高いと思います。基本的な NLog ラッパー用に以下のコードを書きましたが、効率 (StackTrace を使用しない) と使いやすさの完璧なバランスを備えていると思います。

using System;
using System.Runtime.CompilerServices;
using NLog;

namespace ProjectName.Core.Utilities
{
    /// <summary>
    /// Generic NLog wrapper.
    /// </summary>
    public static class Logger
    {
        /// <summary>
        /// Gets or sets the enabled status of the logger.
        /// </summary>
        public static bool Enabled
        {
            get { return LogManager.IsLoggingEnabled(); }
            set
            {
                if (value)
                {                    
                    while (!Enabled) LogManager.EnableLogging();
                }
                else
                {
                    while (Enabled) LogManager.DisableLogging();
                }
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the Trace level.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        public static void Trace(string message, Exception exception = null,
            [CallerFilePath] string callerPath = "",
            [CallerMemberName] string callerMember = "",
            [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Trace, message, exception, callerPath, callerMember, callerLine);
        }

        /// <summary>
        /// Writes the diagnostic message at the Debug level.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        public static void Debug(string message, Exception exception = null,
            [CallerFilePathAttribute] string callerPath = "",
            [CallerMemberName] string callerMember = "",
            [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Debug, message, exception, callerPath, callerMember, callerLine);
        }

        /// <summary>
        /// Writes the diagnostic message at the Info level.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        public static void Info(string message, Exception exception = null,
            [CallerFilePathAttribute] string callerPath = "",
            [CallerMemberName] string callerMember = "",
            [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Info, message, exception, callerPath, callerMember, callerLine);
        }

        /// <summary>
        /// Writes the diagnostic message at the Warn level.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        public static void Warn(string message, Exception exception = null,
            [CallerFilePathAttribute] string callerPath = "",
            [CallerMemberName] string callerMember = "",
            [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Warn, message, exception, callerPath, callerMember, callerLine);
        }

        /// <summary>
        /// Writes the diagnostic message at the Error level.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        public static void Error(string message, Exception exception = null,
            [CallerFilePathAttribute] string callerPath = "",
            [CallerMemberName] string callerMember = "",
            [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Error, message, exception, callerPath, callerMember, callerLine);
        }

        /// <summary>
        /// Writes the diagnostic message at the Fatal level.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        public static void Fatal(string message, Exception exception = null,
            [CallerFilePathAttribute] string callerPath = "",
            [CallerMemberName] string callerMember = "",
            [CallerLineNumber] int callerLine = 0)
        {            
            Log(LogLevel.Fatal, message, exception, callerPath, callerMember, callerLine);
        }

        /// <summary>
        /// Writes the specified diagnostic message.
        /// </summary>
        /// <param name="level"></param>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <param name="callerPath"></param>
        /// <param name="callerMember"></param>
        /// <param name="callerLine"></param>
        private static void Log(LogLevel level, string message, Exception exception = null, string callerPath = "", string callerMember = "", int callerLine = 0)
        {
            // get the source-file-specific logger
            var logger = LogManager.GetLogger(callerPath);

            // quit processing any further if not enabled for the requested logging level
            if (!logger.IsEnabled(level)) return;

            // log the event with caller information bound to it
            var logEvent = new LogEventInfo(level, callerPath, message) {Exception = exception};
            logEvent.Properties.Add("callerpath", callerPath);
            logEvent.Properties.Add("callermember", callerMember);
            logEvent.Properties.Add("callerline", callerLine);
            logger.Log(logEvent);
        }
    }
}

次に、これを NLog.config 内のいずれかのターゲットのレイアウト フィールドに挿入して、呼び出し元の詳細情報を取得してみてください。

${event-context:item=callerpath}:${event-context:item=callermember}(${event-context:item=callerline})
于 2013-03-16T06:04:08.573 に答える
1

ロギング メカニズムの使用を抽象化することをお勧めします。これについては、このブログ投稿で説明しました。これは log4net に関するものですが、どのフレームワークを使用しても同じ原則です。いずれにせよ、ログ アセンブリを使用するすべてのプロジェクトでログ アセンブリが必要ですが、それを抽象化することで、簡単に別のものに置き換えることができます (たとえば、テスト時)。ロギングはインフラストラクチャであるため、インターフェイスと具体的な実装をインフラストラクチャ プロジェクトに配置し、ログを記録するプロジェクトからそれを参照します。

于 2013-03-12T09:06:12.940 に答える