使用Visual Studio中的NLog在多个项目中设置C#解决方案

Rob*_*uch 11 c# dll nlog project visual-studio-2012

我在Visual Studio 2012中的解决方案目前包含两个项目:

  • DLL
  • WPF应用程序(需要DLL的方法)

DLL和WPF应用程序都NLog用于日志记录.目前,每个项目都包含NLogDLL本身.

这是我不明白的:

  1. 我似乎没有必要NLog在每个项目中包含相同的DLL.
  2. 但是,DLL应该可以在其他解决方案中重用,即NLogDLL必须以某种方式包含在DLL项目中.

什么是设置Visual Studio解决方案和/或项目的适当方法?

Dav*_*ras 9

好吧,你需要在你使用它的所有项目中使用DLL,当然你需要使用可执行文件的二进制文件(在你的情况下是WPF应用程序)部署它,以便可以在运行时找到它并使用它.

我倾向于在我的所有项目中做的是创建一个围绕日志引擎的包装器,这样我就不需要引用和依赖特定的第三方日志API,比如Log4Net或NLog,所以我到处使用我的包装器日志记录类然后我仅在包装类的项目和可执行项目中引用日志记录集合以将程序集部署到bin文件夹.

希望这可以帮助 ;-)


小智 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后尝试将其放入NLog.config中某个目标的布局字段中,以获取详细的调用者信息.

${event-context:item=callerpath}:${event-context:item=callermember}(${event-context:item=callerline})
Run Code Online (Sandbox Code Playgroud)