I want to use Microsoft.Extensions.Logging with a DryIoc container.
The default way is to register the factory as an instance, inject it and create a logger:
ILoggerFactory loggerFactory = new LoggerFactory().AddDebug();
container.RegisterInstance(loggerFactory);
// inject factory in constructor
public MyService(ILoggerFactory loggerFactory){
this.logger = loggerFactory.CreateLogger<MyService>()
this.logger.LogInformation("Logger created");
}
But I want a more ASP.NET Core like behavior, where the Logger is directly injected:
// inject logger in constructor
public MyService(ILogger<MyService> logger){
this.logger = logger;
this.logger.LogInformation("Logger created");
}
So I need to create an Instance of the ILoggerFactory due to some configuration, and the ILogger<> Interface must be registered in the container using the "CreateLogger" Method when requested.
I tried using registration with a factory method from https://bitbucket.org/dadhi/dryioc/wiki/SelectConstructorOrFactoryMethod without any success.
Ended up with something like this, but the generic in CreateLogger<> is missing:
container.Register(typeof(ILogger<>), made: Made.Of(() => loggerFactory.CreateLogger<>()));
Maybe anyone can help.
Edit
You have to do this for getting the correct factory method:
var loggerFactoryMethod = typeof(LoggerFactoryExtensions).GetMethod("CreateLogger", new Type[] { typeof(ILoggerFactory) });
I've created and updated a working sample of this using Xamarin.Forms (with Prism and DryIoc) at github.com/dernippel/PrismNetCoreLoggingApp
Here is the full working example based on sample interfaces and classes.
Live code to play is here.
using System;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
// note usage of UseInstance instead of obsolete RegisterInstance
container.UseInstance(new LoggerFactory());
var loggerFactoryMethod = typeof(LoggerFactory).GetMethod("CreateLogger");
container.Register(typeof(ILogger<>), made: Made.Of(
req => loggerFactoryMethod.MakeGenericMethod(req.Parent.ImplementationType),
ServiceInfo.Of<LoggerFactory>()));
container.Register<MyService>();
container.Resolve<MyService>();
}
class MyService
{
public MyService(ILogger<MyService> logger) { logger.Log("Hey!"); }
}
interface ILogger<T>
{
void Log(string msg);
}
class ConsoleLogger<T> : ILogger<T>
{
public void Log(string msg) { Console.WriteLine(typeof(T) + ": " + msg); }
}
class LoggerFactory
{
public ILogger<T> CreateLogger<T>() { return new ConsoleLogger<T>(); }
}
}
For the static method the setup is more simple, you don't need to specify a factory instance via ServiceInfo.Of<LoggerFactory>()
, it will be injected as any other parameter.
Here is the changes (live sample is updated):
var loggerFactoryMethod = typeof(LoggerFactoryExtensions).GetMethod("CreateLogger");
container.Register(typeof(ILogger<>), made: Made.Of(
req => loggerFactoryMethod.MakeGenericMethod(req.Parent.ImplementationType)));
Given the extensions:
public static class LoggerFactoryExtensions
{
public static ILogger<T> CreateLogger<T>(this LoggerFactory f) { return new ConsoleLogger<T>(); }
}