A circular dependency was detected for the service of type: Class Library

0

I trying to make a class library for .Net Standard 2.0. In this class library, I am trying to implement an IServiceCollection extension which allows me to pass a parameter when I consume the Class Library.

However, I'm getting the following exceptions when I try to consume the service.

System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: EntryLog.IEntryLog Lifetime: Scoped ImplementationType: EntryLog.EntryLog': A circular dependency was detected for the service of type 'EntryLog.IEntryLog'.
EntryLog.IEntryLog(EntryLog.EntryLog) -> EntryLog.IEntryLog) (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: EntryLogServiceTester.Worker': A circular dependency was detected for the service of type 'EntryLog.IEntryLog'.
Microsoft.Extensions.Hosting.IHostedService(EntryLogServiceTester.Worker) -> EntryLog.IEntryLog(EntryLog.EntryLog) -> EntryLog.IEntryLog)
  Source=Microsoft.Extensions.DependencyInjection
  StackTrace:
   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at EntryLogServiceTester.Program.Main(String[] args) in C:\Users\JNyingi\source\repos\EntryLogServiceTester\EntryLogServiceTester\Program.cs:line 15

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: EntryLog.IEntryLog Lifetime: Scoped ImplementationType: EntryLog.EntryLog': A circular dependency was detected for the service of type 'EntryLog.IEntryLog'.
EntryLog.IEntryLog(EntryLog.EntryLog) -> EntryLog.IEntryLog

Inner Exception 2:
InvalidOperationException: A circular dependency was detected for the service of type 'EntryLog.IEntryLog'.
EntryLog.IEntryLog(EntryLog.EntryLog) -> EntryLog.IEntryLog

Below is my Service Extension;

    public static class EntryLogExtension
    {
        public static IServiceCollection AddEntryLog(this IServiceCollection services)
        {
            services.AddScoped<IEntryLogProcessor, EntryLogProcessor>();
            services.AddScoped<IEntryLog, EntryLog>();

            return services;
        }

        public static IServiceCollection AddEntryLog(this IServiceCollection services, Uri path)
        {
            services.AddScoped<IEntryLogProcessor, EntryLogProcessor>();
            services.AddScoped<IEntryLog, EntryLog>(s => new EntryLog(s.GetRequiredService<IEntryLog>(), s.GetRequiredService<EntryLogProcessor>(), path));

            return services;
        }

        public static IServiceCollection AddEntryLog(this IServiceCollection services, Uri path, string foldername)
        {
            services.AddScoped<IEntryLogProcessor, EntryLogProcessor>();
            services.AddScoped<IEntryLog, EntryLog>(s => new EntryLog(s.GetRequiredService<IEntryLog>(), s.GetRequiredService<EntryLogProcessor>(), path, foldername));

            return services;
        }
    }

Client DI;

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddEntryLog();
                    services.AddHostedService<Worker>();
                });

My EntryLog.cs

        private readonly IEntryLog EntryLog_;
        private string CompletePath;
        private IEntryLogProcessor _logProcessor;
        private readonly EntrylogContext context;


        public EntryLog(IEntryLog entryLog, IEntryLogProcessor logProcessor)
        {
            this.EntryLog_ = entryLog;
            this._logProcessor = logProcessor;
            EntryLogHandler.BasePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

            this.context = EntrylogContext.context;
        }

        public EntryLog(IEntryLog entryLog,EntryLogProcessor logProcessor, Uri basepath)
        {

            this.EntryLog_ = entryLog;
            EntryLogHandler.BasePath = basepath.LocalPath;
            this._logProcessor = logProcessor;
            this.context = EntrylogContext.context;
        }


        public EntryLog(IEntryLog entryLog,EntryLogProcessor logProcessor, Uri basepath, string foldername)
        {

            this.EntryLog_ = entryLog;
            EntryLogHandler.BasePath = basepath.LocalPath;
            this._logProcessor = logProcessor;
            this.context = EntrylogContext.context;
        }


        public void WriteLog(LogLevel logLevel, string message)
        {
            string foldername = CheckLogLevel(logLevel);

            if (LogFolderValidator(foldername))
            {
                this._logProcessor.WriteLog(this.CompletePath, message);
            }

        }

        public void WriteLog(string message, Exception exception)
        {
            //handle exceptions as critical errors
            string foldername = CheckLogLevel(LogLevel.Error);

            if (LogFolderValidator(foldername))
            {
                string error = message + "\n\n" + FormatMessage(exception);

                this._logProcessor.WriteLog(this.CompletePath, error);
            }
        }

        public async Task WriteLogAsync(LogLevel logLevel, string message)
        {
            string foldername = CheckLogLevel(logLevel);

            if (LogFolderValidator(foldername))
            {
                await this._logProcessor.WriteLogAsync(this.CompletePath, message, this.context.CancellationToken);
            }
        }

        public async Task WriteLogAsync(string message, Exception exception)
        {
            //handle exceptions as critical errors

            string foldername = CheckLogLevel(LogLevel.Error);

            if (LogFolderValidator(foldername))
            {
                string error = message + "\n\n" + FormatMessage(exception);

                await this._logProcessor.WriteLogAsync(this.CompletePath, error, this.context.CancellationToken);
            }
        }


        private string CheckLogLevel(LogLevel logLevel)
        {
            string logLevelstr = String.Empty;

            switch (logLevel)
            {
                case LogLevel.Info:
                    logLevelstr = "Info";
                    break;
                case LogLevel.Warning:
                    logLevelstr = "Warning";
                    break;
                case LogLevel.Error:
                    logLevelstr = "Error";
                    break;
            }

            return logLevelstr;
        } 

        private bool LogFolderValidator(string foldername)
        {
            string completePath = EntryLogHandler.BasePath + '\\' + foldername;
            if (this._logProcessor.CheckLogFolderExists(completePath))
            {
                this.CompletePath = completePath;
                return true;
            }
            else
            {
                try
                { 
                    this._logProcessor.CreateLogFolder(completePath);
                    this.CompletePath = completePath;
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }

            }
        }

        private string FormatMessage(Exception ex)
        {
            return ex.Message.ToString() + "\n" + ex.InnerException.ToString();
        }

My IEntryLog.cs

        void WriteLog(LogLevel logLevel, string message);
        void WriteLog(string message, Exception exception);
        Task WriteLogAsync(LogLevel logLevel, string message);
        Task WriteLogAsync(string message, Exception exception);

My IEntryLogProcessor

        void CreateLogFolder();
        void CreateLogFolder(string completepath);
        bool CheckLogFolderExists(string folderPath);
        void WriteLog(string path, string message);
        Task WriteLogAsync(string path, string message, CancellationToken cancellationToken);

I've tried converting to Transient and Singleton with no success.I expect the Iservicecollection to work without a hitch.

c#
dependency-injection
circular-dependency
.net-standard-2.0
asked on Stack Overflow May 16, 2020 by John Nyingi

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0