简体   繁体   English

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

[英]Setting up C# solution with multiple projects using NLog in Visual Studio

My solution in Visual Studio 2012 currently contains two projects: 我在Visual Studio 2012中的解决方案目前包含两个项目:

  • DLL DLL
  • WPF application (which requires methods of the DLL) WPF应用程序(需要DLL的方法)

Both, the DLL and the WPF application, use NLog for logging. DLL和WPF应用程序都使用NLog进行日志记录。 Currently each project contains the NLog DLL itself. 目前,每个项目都包含NLog DLL本身。

Here is what I don't understand: 这是我不明白的:

  1. It seems unnecessary to me including the identical NLog DLL in each project. 我似乎没有必要在每个项目中包含相同的NLog DLL。
  2. The DLL however shall be reusable in other solutions, ie somehow the NLog DLL must be contained in the DLL project. 但是,DLL应该可以在其他解决方案中重用,也就是说, NLog DLL必须以某种方式包含在DLL项目中。

What would be an adequate way of setting up the Visual Studio solution and/or projects? 什么是设置Visual Studio解决方案和/或项目的适当方法?

well you need the DLL in all projects where you use it and surely you need it deployed with the binaries of the executable (WPF application in your case) so that it can be found and used at runtime. 好吧,你需要在你使用它的所有项目中使用DLL,当然你需要使用可执行文件的二进制文件(在你的情况下是WPF应用程序)部署它,以便可以在运行时找到它并使用它。

what I tend to do in all my projects is create a wrapper around the logging engine so that I do not need to reference and depend on specific third party logging APIs, like Log4Net or NLog, so I use my wrapper logging class everywhere and then I have a reference to the logging asembly only in the wrapper class's project and in the executable project to have the assembly deployed to the bin folder. 我倾向于在我的所有项目中做的是创建一个围绕日志引擎的包装器,这样我就不需要引用和依赖特定的第三方日志API,比如Log4Net或NLog,所以我到处使用我的包装器日志记录类然后我仅在包装类的项目和可执行项目中引用日志记录集合以将程序集部署到bin文件夹。

hope this helps ;-) 希望这可以帮助 ;-)

If your DLL is just a core library you plan on sharing among various projects, it may be wise to add an NLog reference and wrapper code to just that library, then make sure that any consumer application (such as your WPF project) has an NLog.config file associated with it. 如果您的DLL只是您计划在各种项目之间共享的核心库,那么将NLog引用和包装代码添加到该库可能是明智的,然后确保任何消费者应用程序(例如您的WPF项目)都有NLog与之关联的.config文件。

Since you're using VS2012 I'm assuming you're also most likely working with .NET 4.5 which allows you to take advantage of the new caller info attributes. 由于您使用的是VS2012,我假设您最有可能使用.NET 4.5,它允许您利用新的调用者信息属性。 I've written the following code below for a basic NLog wrapper and believe it has the perfect balance of efficiency (doesn't use StackTrace) and usability. 我已经为下面的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);
        }
    }
}

Then try throwing this into the layout field of one of the targets in your NLog.config to grab the detailed caller information. 然后尝试将其放入NLog.config中某个目标的布局字段中,以获取详细的调用者信息。

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

You better abstract the use of your logging mechanism. 您最好抽象使用日志记录机制。 I described this in this blog post , it's about log4net but is the same principle whatever framework you use. 我在这篇博文中描述了这个,它是关于log4net的,但是无论你使用什么框架都是相同的原则。 In any case, you need the log assembly in every project where you use it, but by abstracting it it's easy to replace it by something else (when testing for example). 在任何情况下,您需要在每个使用它的项目中使用日志程序集,但通过抽象它可以很容易地用其他东西替换它(例如在测试时)。 Logging is infrastructure, so you would put the interfaces and concrete implementation in an infrastructure project, and reference that one from the projects in which you want to log. 日志记录是基础结构,因此您可以将接口和具体实现放在基础结构项目中,并从要记录的项目中引用该接口和具体实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在一个解决方案 c# 上为多个项目使用 NLog - Using NLog for several projects on one solution c# 为解决方案中的多个 Visual Studio 2012 C# 项目启动调试器时出现 Visual Studio 2017 警告错误 - Visual Studio 2017 warning errors when starting a debugger for multiple Visual Studio 2012 C# projects in a solution 如何从同一解决方案捆绑多个项目(不使用Visual Studio) - How to tie up multiple projects from same solution (not using Visual Studio) c# .net - 关于 Visual Studio 2010 中同一解决方案下的多个项目的问题 - c# .net - Question about multiple Projects under same solution in Visual Studio 2010 使用 CMake(针对 Visual Studio 的 CMake)在同一解决方案中创建 C# 和 C++/CLR 项目 - Creating C# and C++/CLR projects in the same solution using CMake (CMake targeting visual studio) 具有许多项目的Visual Studio C#解决方案(依赖项) - Visual Studio C# Solution with many Projects (Dependencies) 使用C#和Powershell项目构建Visual Studio解决方案 - Build a Visual Studio Solution with C# AND Powershell projects 我可以使用 c# 在 Visual Studio 中的同一解决方案中使用两个项目吗 - Can I use two projects in same solution in Visual Studio using c# 具有多个项目的Visual Studio解决方案:参考路径 - Visual Studio Solution with Multiple Projects: Reference Paths 以编程方式将多个项目添加到Visual Studio解决方案中? - Add multiple projects programmatically into Visual Studio solution?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM