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



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

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

DLL和WPF应用程序都使用NLog进行日志记录。目前,每个项目本身都包含NLog DLL。

我不明白的是:

  1. 对我来说似乎没有必要在每个项目中包括相同的NLog DLL。
  2. DLL必须在其他解决方案中可重用,即NLog DLL必须以某种方式包含在DLL项目中。

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

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

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

-)

如果您的DLL只是一个核心库,您计划在各个项目之间共享,那么向该库添加NLog引用和包装器代码可能是明智的,然后确保任何消费者应用程序(例如您的WPF项目)都有NLog。与之关联的配置文件

因为你正在使用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中某个目标的布局字段中。配置以获取详细的呼叫者信息。

${event-context:item=callerpath}:${event-context:item=callermember}(${event-context:item=callerline})

您最好抽象日志机制的使用。我在这篇博文中描述了这一点,它是关于log4net的,但无论你使用什么框架,原理都是一样的。在任何情况下,您都需要在使用它的每个项目中使用日志程序集,但是通过抽象它,很容易用其他东西替换它(例如在测试时)。日志记录是基础设施,因此您可以将接口和具体实现放在基础设施项目中,并从您想要记录日志的项目中引用该项目。

最新更新