My solution in Visual Studio 2012 currently contains two projects:
Both, the DLL an
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.
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. 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.
using System;
using System.Runtime.CompilerServices;
using NLog;
namespace ProjectName.Core.Utilities
{
///
/// Generic NLog wrapper.
///
public static class Logger
{
///
/// Gets or sets the enabled status of the logger.
///
public static bool Enabled
{
get { return LogManager.IsLoggingEnabled(); }
set
{
if (value)
{
while (!Enabled) LogManager.EnableLogging();
}
else
{
while (Enabled) LogManager.DisableLogging();
}
}
}
///
/// Writes the diagnostic message at the Trace level.
///
///
///
///
///
///
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);
}
///
/// Writes the diagnostic message at the Debug level.
///
///
///
///
///
///
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);
}
///
/// Writes the diagnostic message at the Info level.
///
///
///
///
///
///
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);
}
///
/// Writes the diagnostic message at the Warn level.
///
///
///
///
///
///
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);
}
///
/// Writes the diagnostic message at the Error level.
///
///
///
///
///
///
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);
}
///
/// Writes the diagnostic message at the Fatal level.
///
///
///
///
///
///
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);
}
///
/// Writes the specified diagnostic message.
///
///
///
///
///
///
///
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.
${event-context:item=callerpath}:${event-context:item=callermember}(${event-context:item=callerline})