【问题标题】:.Net Core custom logger circular dependency injection reference / infinite loop.Net Core 自定义记录器循环依赖注入参考/无限循环
【发布时间】:2020-10-06 19:16:13
【问题描述】:

我试图编写一个客户 ILogger / ILoggerProvider,它依赖于一个依赖于 ILogger 的服务 :) 这给我留下了循环引用和无限循环。

如何修改此代码以避免循环引用?

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());
        }
    }

如果可能,我想保持结构相似,而不是用通用主机和 IHostBuilder 重写。

【问题讨论】:

    标签: asp.net-core logging .net-core dependency-injection ilogger


    【解决方案1】:

    你可以有一个第三个类来引用这两个服务,你只需要在你需要服务的地方依赖注入这个类。

    一个类似的问题here,你可以看看。

    【讨论】:

      猜你喜欢
      • 2018-03-03
      • 2014-12-17
      • 2018-10-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      相关资源
      最近更新 更多