Я пытался написать клиентский ILogger / ILoggerProvider, который зависит от службы, которая зависит от ILogger :) Это оставляет мне круговую ссылку и бесконечное l oop.
Как могло Я модифицирую этот код, чтобы избежать циклической ссылки?
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());
}
}
Если возможно, я хотел бы сохранить аналогичную структуру и не переписывать с помощью общего c хоста и IHostBuilder.