title: How to use serilog in a referenced class library and use with CallerMember, CallerFilePath (not asp.net core)
body: <p>I am working on a WPF application and can sucessfully setup serilog and access it's static method by placing it inside App.xaml.cs,</p>
  
  <p>However I am wanting to also log inside the various referenced class libraries in the project.</p>
  
  <p>As I can't reference the main application from the class library itself, due to a circular dependency, what is the best way to perform logging in these class libraries?</p>
  
  <pre><code>public class LogManager : IMLogManager
      {
          #region Constructor
  
          public LogManager()
          {
              Log.Logger = new LoggerConfiguration()
                           .MinimumLevel.Debug()
                           .Enrich.FromLogContext()
                           .WriteTo.Console(LogEventLevel.Debug, OutputTemplate, theme: AnsiConsoleTheme.Code)
                           .WriteTo.Async(a =&gt; a.File("./log/log.log",
                                                      LogEventLevel.Debug,
                                                      OutputTemplate,
                                                      rollingInterval: RollingInterval.Day,
                                                      encoding: Encoding.UTF8,
                                                      buffered: true,
                                                      rollOnFileSizeLimit: true))
                           .CreateLogger();
          }
  
          #endregion
  
          #region Private properties
  
          /// &lt;summary&gt;
          ///     Template ghi log.
          /// &lt;/summary&gt;
          public static string OutputTemplate =&gt;
              "[{Timestamp:dd-MM-yyyy HH:mm:ss.fff} {Level:u3}] source {SourceContext} ::: {Message:lj}{NewLine}{Exception}{NewLine}";
  
          #endregion
  
          #region Private methods
  
          private static string FormatMessage(string message,
                                              string memberName = "",
                                              string filePath = "",
                                              int lineNumber = 0)
              =&gt; $"in method [{Path.GetFileNameWithoutExtension(filePath)} &gt; {memberName}]\r\n\tat {filePath}:{lineNumber}\r\n{message}";
  
          #endregion
  
          #region Private fields
  
          #endregion
  
          #region Implementation of IMLogManager
  
          /// &lt;summary&gt;
          ///     Write app log.
          /// &lt;/summary&gt;
          /// &lt;param name="level"&gt;&lt;/param&gt;
          /// &lt;param name="message"&gt;&lt;/param&gt;
          /// &lt;param name="exception"&gt;&lt;/param&gt;
          /// &lt;param name="memberName"&gt;&lt;/param&gt;
          /// &lt;param name="filePath"&gt;&lt;/param&gt;
          /// &lt;param name="lineNumber"&gt;&lt;/param&gt;
          public void WriteLog(LogEventLevel level,
                               string message,
                               Exception exception = null,
                               [CallerMemberName] string memberName = "",
                               [CallerFilePath] string filePath = "",
                               [CallerLineNumber] int lineNumber = 0)
          {
              switch (level)
              {
                  case LogEventLevel.Verbose:
                      Log.Verbose(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Debug:
                      Log.Debug(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Information:
                      Log.Information(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Warning:
                      Log.Warning(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Error:
                      Log.Error(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Fatal:
                      Log.Fatal(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  default:
                      throw new ArgumentOutOfRangeException(nameof(level), level, null);
              }
          }
  
          public void WriteLog&lt;T&gt;(LogEventLevel level,
                                  string message,
                                  Exception exception = null,
                                  [CallerMemberName] string memberName = "",
                                  [CallerFilePath] string filePath = "",
                                  [CallerLineNumber] int lineNumber = 0) where T : class
          {
              var log = Log.ForContext&lt;T&gt;()
                           .ForContext("MemberName", memberName)
                           .ForContext("FilePath", filePath)
                           .ForContext("FileName", Path.GetFileNameWithoutExtension(filePath))
                           .ForContext("LineNumber", lineNumber);
              switch (level)
              {
                  case LogEventLevel.Verbose:
                      log.Verbose(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Debug:
                      log.Debug(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Information:
                      log.Information(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Warning:
                      log.Warning(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Error:
                      log.Error(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  case LogEventLevel.Fatal:
                      log.Fatal(exception, FormatMessage(message, memberName, filePath, lineNumber));
  
                      break;
  
                  default:
                      throw new ArgumentOutOfRangeException(nameof(level), level, null);
              }
          }
  
          public void CloseAndFlush()
          {
              Log.CloseAndFlush();
          }
  
          #endregion
      }
  </code></pre>