simpleinjector / SimpleInjector

An easy, flexible, and fast Dependency Injection library that promotes best practice to steer developers towards the pit of success.
https://simpleinjector.org
MIT License
1.21k stars 155 forks source link

Serilog registration #970

Closed osekj closed 8 months ago

osekj commented 1 year ago

There a few issues related to the given problem, but all of them are several years old. What is current and the easiest way to register Serilog? In my case it would be loggin using MSSqlServer sink.

dotnetjunkie commented 1 year ago

Can you supply me with more information about what you want to achieve, which resources you found, and what's not working for you considering those resources?

Ergamon commented 1 year ago

I dont think much has changed in the past years. The documentation on contextual logging is under Advanced scenarios. This is not related to a specific logging framework.

The only problem with Serilog is, that Serilog has a static method to create the loggers, while SimpleInjector wants generic loggers.

So all you have to do is write an adapter between these two approaches:

public sealed class Logger<T> : ILogger
{
  private readonly ILogger _logger;

  public Logger()
  {
    _logger = Log.ForContext<T>();
  }

  void ILogger.Write(LogEvent logEvent)
  {
    _logger.Write(logEvent);
  }
}

That is basically all you need for Serilog SimpleInjector registration.

_The implementation is a little longer when you are on older frameworks without default interface implementations. But also solvable, just write every method by using the _logger field.__

With this class you can just set everything up as described in the SimpleInjector documentation.

Here an example:

internal class Program
{
  static void Main(string[] args)
  {
    Log.Logger = new LoggerConfiguration()
      .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}")
      .CreateLogger();

    var container = new Container();
    container.Register<Foo>();
    container.RegisterConditional(
      typeof(ILogger),
      c => typeof(Logger<>).MakeGenericType(c.Consumer!.ImplementationType),
      Lifestyle.Singleton,
      c => true);

    container.Verify();

    var foo = container.GetInstance<Foo>();
    foo.DoWork();
  }
}

public class Foo
{
  private readonly ILogger _logger;

  public Foo(ILogger logger)
  {
    _logger = logger;
  }

  public void DoWork()
  {
    _logger.Information("doing work");
  }
}