我在Visual Studio解决方案目前2012包含两个项目:
这两个,DLL和WPF应用程序,使用NLog
用于记录。 目前,每个项目包含NLog
DLL本身。
以下是我不明白:
- 它似乎没有必要对我来说,包括相同的
NLog
在每个项目中的DLL。 - 然而,DLL应在其他的解决方案,即在某种程度上可重复使用的
NLog
DLL必须包含在DLL项目。
什么是建立在Visual Studio解决方案和/或项目的适当方法是什么?
那么你需要在你使用它,你一定需要它部署的可执行文件(在你的情况WPF应用程序)的二进制文件,以便它可以被发现并在运行时使用的所有项目的DLL。
我倾向于在我所有的项目做的是创建一个围绕日志引擎的包装,这样我就不需要参考,并依赖于特定的第三方日志记录API,像log4net的或NLOG,所以我到处,然后我用我的包装日志类有一个参考asembly只在包装类的项目,并在项目执行记录有部署到bin文件夹中的程序集。
希望这可以帮助 ;-)
如果你的DLL就是你打算在各个项目之间共享一个核心库,它可能是明智的添加NLOG参考和包装代码只是该库,然后确保任何消费者应用程序(如您的WPF项目)具有NLOG的.config与它相关的文件。
由于您使用VS2012我假设你也最有可能与.NET 4.5,它允许你采取新的来电者信息属性的优势合作。 我已经写了下面的下面的代码为基础NLOG包装,并相信它有效率(不使用堆栈跟踪)和可用性的完美平衡。
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})
你最好抽象的使用日志记录机制。 我在此说明本博客文章 ,它是关于log4net的,但无论您使用的框架同样的原则。 在任何情况下,你需要在你使用的每个项目的日志组件,但它抽象很容易被其他的东西(例如测试时)来代替它。 日志为基础,所以你会投入基础设施项目的接口和具体落实,并说明一个从项目中要记录。