2013-03-12 5 views
10

moje rozwiązanie w Visual Studio 2012 zawiera obecnie dwa projekty:Konfigurowanie C# rozwiązanie z wielu projektów wykorzystujących NLog w Visual Studio

  • DLL
  • aplikacji WPF (co wymaga metod DLL)

Zarówno w przypadku aplikacji DLL, jak i WPF, do rejestrowania należy używać NLog. Obecnie każdy projekt zawiera samą bibliotekę NLog.

Oto czego nie rozumiem:

  1. Wydaje mi niepotrzebne tym identyczną NLog DLL w każdym projekcie.
  2. DLL może być jednak ponownie użyty w innych rozwiązaniach, tzn. Biblioteka DLL musi być w jakiś sposób zawarta w projekcie DLL.

Jaki byłby odpowiedni sposób konfigurowania rozwiązania i/lub projektów Visual Studio?

+1

Zostaw to tak, jak jest teraz, powiedziałbym. Będzie tylko jedna kopia biblioteki DLL dla każdego zestawu, który chce z niego korzystać.Jeśli wykonywalny zestaw, który używa odniesień DLL (powiedzmy), dwa inne zespoły biblioteki klas, które również używają biblioteki DLL, * nadal * uzyskasz tylko jedną bibliotekę DLL w folderze wyjściowym dla zestawu wykonywalnego. –

Odpowiedz

9

Cóż, potrzebujesz DLL we wszystkich projektach, w których go używasz i na pewno potrzebujesz go wdrożonego z plikami binarnymi pliku wykonywalnego (aplikacja WPF w twoim przypadku), aby można go było znaleźć i używać w środowisku wykonawczym.

to, co robię we wszystkich moich projektach, to tworzenie wrappera wokół mechanizmu rejestrowania, aby nie musieć się odwoływać i polegać na określonych interfejsach API do rejestrowania stron trzecich, takich jak Log4Net lub NLog, więc używam swojej klasy rejestrowania opakowującego wszędzie, a następnie odwołuję się do zespołu rejestrowania tylko w projekcie klasy opakowania i do projektu wykonywalnego, aby zespół został wdrożony w folderze bin.

mam nadzieję, że to pomoże ;-)

1

Lepiej streszczenie wykorzystania mechanizmu logowania. Opisałem to w this blog post, chodzi o log4net, ale jest to ta sama zasada, niezależnie od używanego frameworka. W każdym razie potrzebujesz zestawu dziennika w każdym projekcie, w którym go używasz, ale przez jego streszczenie łatwo jest go zastąpić czymś innym (np. Podczas testowania). Rejestrowanie to infrastruktura, więc można umieścić interfejsy i konkretne implementacje w projekcie infrastruktury i odwołać się do tego z projektów, w których chcesz się logować.

+0

To jest dobre i zgadzam się, ale co, jeśli DI nie może być wdrożony. Chciałbym zachować oddzielne logowanie i odnosić się do całego rozwiązania w wielu projektach. – JoshYates1980

7

Jeśli twoja biblioteka DLL jest tylko biblioteką rdzeniową, którą planujesz udostępniać w ramach różnych projektów, dobrym pomysłem może być dodanie kodu źródłowego i kodu NLOG tylko do tej biblioteki, a następnie upewnić się, że każda aplikacja konsumencka (taka jak Twój projekt WPF)) ma powiązany plik NLog.config.

Ponieważ używasz VS2012, zakładam, że najprawdopodobniej będziesz także pracował z .NET 4.5, który pozwala ci korzystać z nowych atrybutów informacji o dzwoniącym. Poniżej napisałem poniższy kod dla podstawowego opakowania NLog i wierzę, że ma idealną równowagę efektywności (nie używa StackTrace) i użyteczność.

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); 
     } 
    } 
} 

Następnie spróbuj rzucając je w polu Układ jeden z celów w plik NLog.config aby pobrać szczegółowe informacje o abonencie wywołującym.

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

Może również targetować .net 4.0, jeśli dodasz odwołanie do "Kompilacji Kompilacji Microsoft BCL" (via NuGet) – Xilmiki

+0

Dlaczego ustawiający dla Włączonego używa pętli while do sprawdzania aktualnego statusu Włączonego? Czy nie wystarczy wywołać LogManager.EnableLogging(), jeśli wartość jest prawdą, a LogManager.DisableLogging() w przeciwnym razie? –

+1

Po prostu odkryłem, że istnieje licznik włączania logu i że odpowiednio włączają i wyłączają zwiększanie lub zmniejszanie tego licznika. Uważam, że nazewnictwo jest trochę mylące, mam nadzieję, że ktoś inny się z tego dowie. –

Powiązane problemy