Исключение циклической зависимости при создании пользовательского средства ведения журнала, использующего параметры, с вC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Исключение циклической зависимости при создании пользовательского средства ведения журнала, использующего параметры, с в

Сообщение Anonymous »

У меня есть рабочее приложение .NET Core, и я хочу добавить собственный регистратор файлов, поскольку Microsoft.Extensions.Logging не предоставляет этого. Я не хочу использовать для этого дополнительный пакет (например, Serilog).
Я помещаю информацию о каталоге журнала и файле журнала в свой класс параметров. Этот класс параметров также имеет валидатор, реализующий интерфейс IValidateOptions. В этот валидатор вводится экземпляр средства ведения журнала для регистрации ошибок проверки, если они возникли.
Провайдеру средства ведения журнала файлов необходимо внедрить монитор параметров, чтобы получить доступ к конфигурациям каталога и файлов.
К сожалению, при запуске приложения возникает исключение.

System.AggregateException: «Некоторые службы не могут работать
создан'

с содержимым

Ошибка при проверке дескриптора службы ' ServiceType:
Microsoft.Extensions.Hosting.IHostApplicationLifetime Срок действия:
Singleton ImplementationType:
Microsoft.Extensions.Hosting.Internal.ApplicationLifetime': Для службы обнаружена циклическая
зависимость введите
'Microsoft.Extensions.Logging.ILoggerFactory'.
Microsoft.Extensions.Hosting.IHostApplicationLifetime(Microsoft.Extensions.Hosting.Internal.ApplicationLifetime)
-> Microsoft.Extensions.Logging.ILogger (Microsoft.Extensions.Logging.Logger)
-> Microsoft.Extensions.Logging.ILoggerFactory(Microsoft.Extensions.Logging .LoggerFactory)
-> System.Collections.Generic.IEnumerable
-> Microsoft.Extensions.Logging.ILoggerProvider(Ajifsdjfijgsidjfijsdifjisd.FileLoggerProvider)
-> Microsoft .Extensions.Options.IOptionsMonitor(Microsoft.Extensions.Options.OptionsMonitor)
-> Microsoft.Extensions.Options.IOptionsFactory(Microsoft.Extensions.Options. OptionsFactory)
-> System.Collections.Generic.IEnumerable
-> Microsoft.Extensions.Options.IValidateOptions(MyLib.MyOptionsValidator)
-> Microsoft.Extensions.Logging.ILogger(Microsoft.Extensions.Logging.Logger)
-> Microsoft.Extensions.Logging.ILoggerFactory

Это имеет смысл, поскольку при внедрении нового экземпляра средства ведения журнала это человеку вводят варианты. И это запустит валидатор, который введет новый экземпляр регистратора. И все начинается заново.

Logger => Параметры => Валидатор => Регистратор => Параметры => Валидатор =>
Logger => Параметры => Валидатор => ...

Я не знаю, как решить эту проблему, поскольку моему регистратору файлов необходим доступ к параметрам конфигурации и мой валидатор параметров должен регистрировать ошибки проверки.
Есть идеи?

Если вы хотите получить обзор приложения, вот что я сделал, чтобы воспроизвести его:
  • Создайте новый проект .NET Core Worker
  • Наверх в файл .csproj и добавьте в первую группу элементов, чтобы получить доступ к Kestrel и веб-материалам.
  • Я добавить библиотеку MyLib в проект и ссылаться на нее в основном проекте
  • В библиотеке я создаю класс параметров, содержащий информацию для регистратора файлов
.

Код: Выделить всё

public class MyOptions
{
public string DirectoryPath { get; set; }
public string FileName { get; set; }
}
  • Я также добавляю простой пример средства проверки параметров, в котором используется экземпляр журнала
< р>.

Код: Выделить всё

public class MyOptionsValidator : IValidateOptions
{
private readonly ILogger logger;

public MyOptionsValidator(ILogger logger)
{
this.logger = logger;
}

public ValidateOptionsResult Validate(string name, MyOptions myOptions)
{
if (string.IsNullOrEmpty(myOptions.DirectoryPath) || string.IsNullOrEmpty(myOptions.FileName))
{
logger.LogWarning("Invalid");

return ValidateOptionsResult.Fail("Invalid");
}

return ValidateOptionsResult.Success;
}
}
  • Я добавляю параметры в файл appsettings.json
.
  • Я добавляю параметры в файл appsettings.json
.
  • Я добавляю параметры в файл appsettings.json
.
  • Я добавляю параметры в файл appsettings.json
.
  • Я добавляю параметры в файл appsettings.json
.
  • Я добавляю параметры в файл appsettings.json
.
  • Я добавляю параметры в файл appsettings.json.
  • р>

    Код: Выделить всё

    "MyOptions": {
    "DirectoryPath": "C:\\Logs",
    "FileName": "log.log"
    }
    
    В библиотеке я расширяю коллекцию сервисов для регистрации вариантов проверки
.

Код: Выделить всё

public static class IServiceCollectionExtensions
{
public static IServiceCollection AddMyLib(this IServiceCollection services) =>
services.AddSingleton();
}
  • В основном проекте я настраиваю часть журналирования. Сначала я создаю новый файловый регистратор. Поскольку этот сервис не может быть «обычным» и не будет добавлен в контейнер DI, я просто ожидаю, что необходимые параметры будут в конструкторе
.

Код: Выделить всё

internal class FileLogger : ILogger
{
private readonly string fullLogFilePath;

public FileLogger(string logDirectoryPath, string logFileName)
{
if (!Directory.Exists(logDirectoryPath))
Directory.CreateDirectory(logDirectoryPath);

fullLogFilePath = Path.Combine(logDirectoryPath, logFileName);
}

public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
{
if (!IsEnabled(logLevel))
return;

using StreamWriter streamWriter = new StreamWriter(fullLogFilePath, true);
streamWriter.WriteLine($"[{DateTime.Now}] [{logLevel}] {formatter(state, exception)} {exception?.StackTrace}");
}

public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;

public IDisposable BeginScope(TState state) => null;
}
  • Чтобы обслуживать этот регистратор, я добавил поставщика
.

Код: Выделить всё

internal class FileLoggerProvider : ILoggerProvider
{
private readonly IOptionsMonitor myOptionsMonitor;

public FileLoggerProvider(IOptionsMonitor myOptionsMonitor)
{
this.myOptionsMonitor = myOptionsMonitor;
}

public void Dispose()
{
}

public ILogger CreateLogger(string categoryName)
{
MyOptions myOptions = myOptionsMonitor.CurrentValue;

return new FileLogger(myOptions.DirectoryPath, myOptions.FileName);
}
}
  • и расширьте построитель журналов, добавив файловый регистратор
.
  • и расширьте построитель журналов, добавив файловый регистратор
.
  • расширьте построитель журналов, добавив файловый регистратор
.
  • р>

    Код: Выделить всё

    public static class ILoggingBuilderExtensions
    {
    public static void AddFileLogger(this ILoggingBuilder loggingBuilder)
    {
    loggingBuilder.Services.AddSingleton();
    }
    }
    
    Как и в проекте веб-API, я добавил файл запуска для настройки всех параметров и служб.
    < /ul>
    .

    Код: Выделить всё

    internal class Startup
    {
    private readonly IConfiguration configuration;
    
    public Startup(IConfiguration configuration)
    {
    this.configuration = configuration;
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddMyLib();
    
    IConfigurationSection myOptionsSection = configuration.GetSection("MyOptions");
    services.Configure(myOptionsSection);
    }
    
    public void Configure(IApplicationBuilder applicationBuilder)
    {
    }
    }
    
  • В последней части я обновил файл программы до этого
.< /p>

Код: Выделить всё

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(loggingBuilder =>
{
loggingBuilder
.ClearProviders()
.AddConsole()
.AddEventLog()
.AddFileLogger();
})
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.UseKestrel().UseStartup();
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService();
});
}
  • Вы должны получить исключение System.AggregateException из-за циклической зависимости


Подробнее здесь: https://stackoverflow.com/questions/646 ... -options-w
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»