2013-03-12 66 views
10

我的解決方案多個項目C#解決方案2012目前包含兩個項目:設置在Visual Studio中使用NLOG在Visual Studio

  • DLL
  • WPF應用程序(這需要DLL的方法)

DLL和WPF應用程序都使用NLog進行日誌記錄。目前每個項目都包含NLog DLL本身。

這是我不明白:

  1. 似乎沒有必要對我來說,包括每個項目的相同NLog DLL。然而
  2. 的DLL應在其他可重複使用的解決方案,即以某種方式NLog DLL必須包含在DLL項目。

什麼是設置Visual Studio解決方案和/或項目的適當方式?

+1

讓它像現在這樣,我會說。每個想要使用它的程序集只有一個DLL副本。如果使用該DLL的可執行程序集引用(說)兩個其他類庫程序集也使用該DLL,那麼您將*只*得到可執行程序集的輸出文件夾中的一個DLL。 – 2013-03-12 08:45:06

回答

9

以及你需要在你使用它,你一定需要它部署的可執行文件(在你的情況WPF應用程序)的二進制文件,以便它可以被發現並在運行時使用的所有項目的DLL。

我在我的所有項目中傾向於做的事情是在日誌引擎周圍創建一個包裝,這樣我就不需要引用和依賴特定的第三方日誌API,如Log4Net或NLog,所以我使用我的包裝日誌記錄類無處不在,然後我只在包裝類的項目和可執行項目中引用了日誌組件,才能將程序集部署到bin文件夾。

希望這有助於;-)

1

你最好抽象使用日誌記錄機制。我在this blog post中描述過這個問題,它是關於log4net的,但是無論你使用什麼框架都是一樣的原理。在任何情況下,您都需要在使用它的每個項目中使用日誌程序集,但通過抽象它可以很容易地將其替換爲其他東西(例如測試時)。日誌記錄是基礎設施,因此您可以將接口和具體實現放入基礎架構項目中,並從您想要記錄的項目中引用該接口和具體實現。

+0

這很好,我同意,但如果DI無法實施,該怎麼辦?我想在整個解決方案中將多個項目中的日誌記錄分開並引用。 – JoshYates1980 2016-02-19 17:09:01

7

如果您的DLL只是您計劃在各種項目之間共享的核心庫,那麼可以明智地將NLog引用和包裝代碼添加到該庫中,然後確保任何使用者應用程序(例如您的WPF項目)有一個與之關聯的NLog.config文件。

由於您使用的是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.config中的其中一個目標的佈局字段以獲取詳細的來電者信息。

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

如果您添加對「Microsoft BCL構建組件」的引用(通過NuGet),也可以以.net 4.0爲目標 – Xilmiki 2014-07-16 07:57:18

+0

爲什麼Enabled的setter使用while循環來檢查Enabled的當前狀態?如果值爲true,並且LogManager.DisableLogging()否則只需調用LogManager.EnableLogging()就足夠了嗎? – 2015-05-06 15:36:04

+1

剛剛發現有一個日誌啓用計數器,並且啓用和禁用分別增加或減少該計數器。我發現命名有點混亂,希望別人從中學到東西。 – 2015-05-06 15:37:14