在Visual Studio中使用NLog设置多个项目的c#解决方案
本文关键字:项目 解决方案 设置 NLog Studio Visual | 更新日期: 2023-09-27 18:03:41
我在Visual Studio 2012中的解决方案目前包含两个项目:
- DLL
- WPF应用程序(需要DLL方法)
DLL和WPF应用程序都使用NLog
进行日志记录。目前,每个项目本身都包含NLog
DLL。
我不明白的是:
- 对我来说似乎没有必要在每个项目中包括相同的
NLog
DLL。 - 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的,但无论你使用什么框架,原理都是一样的。在任何情况下,您都需要在使用它的每个项目中使用日志程序集,但是通过抽象它,很容易用其他东西替换它(例如在测试时)。日志记录是基础设施,因此您可以将接口和具体实现放在基础设施项目中,并从您想要记录日志的项目中引用该项目。