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.
User contributions licensed under CC BY-SA 3.0