I tried to write a customer ILogger / ILoggerProvider that has a dependency on a service that has a dependency on ILogger :) That leaves me with a circular reference and an infinite loop.
How could I modify this code to avoid the circular reference?
class Program { static void Main(string[] args) { var configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build(); var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton<IDependentOnLoggerService, MyService>(); serviceCollection.AddLogging(loggingBuilder => { loggingBuilder.AddConfiguration(configuration.GetSection("Logging")); loggingBuilder.AddConsole(); }); serviceCollection.AddCustomLogger(); using (var serviceProvider = serviceCollection.BuildServiceProvider()) { var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); var logger = loggerFactory.CreateLogger<Program>(); logger.LogInformation("hello world"); } } } public interface IDependentOnLoggerService { void DoWork(); } public class MyService : IDependentOnLoggerService { private ILogger logger; public MyService(ILoggerFactory loggerFactory) { this.logger = loggerFactory.CreateLogger<MyService>(); this.logger.LogInformation("MyService create"); } public void DoWork() { this.logger.LogInformation("Doing work"); } } public static class ServiceCollectionExtensions { public static void AddCustomLogger(this IServiceCollection serviceCollection) { serviceCollection.AddLogging(loggingBuilder => { loggingBuilder.AddCustomLogger(); }); } private static ILoggingBuilder AddCustomLogger(this ILoggingBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, CustomLoggerProvider>( serviceProvider => { // this causes circulation dependency injection, resolving IDependentOnLoggerService will try to resolve an ILogger which will bring it right back here var loggerDependentService = serviceProvider.GetService<IDependentOnLoggerService>(); return new CustomLoggerProvider(loggerDependentService); })); return builder; } } public class CustomLoggerProvider : ILoggerProvider { IDependentOnLoggerService dependentOnLoggerService; public CustomLoggerProvider(IDependentOnLoggerService dependentOnLoggerService) { this.dependentOnLoggerService = dependentOnLoggerService; } public ILogger CreateLogger(string categoryName) { return new CustomLogger(this.dependentOnLoggerService); } public void Dispose() { } } public class CustomLogger : ILogger { IDependentOnLoggerService dependentOnLoggerService; public CustomLogger(IDependentOnLoggerService dependentOnLoggerService) { this.dependentOnLoggerService = dependentOnLoggerService; } public IDisposable BeginScope<TState>(TState state) { return null; } public bool IsEnabled(LogLevel logLevel) { return true; } public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { this.dependentOnLoggerService.DoWork(); Console.WriteLine(state.ToString()); } }