.NET Core DI и подклассы
Новинка .NET Core здесь. Я искал другую документацию, ветку или руководство, которое отвечает на мои вопросы, но не могу найти его. Если вы думаете, что да, укажите на это.
Я пытаюсь создать простое консольное приложение .NET 5 с DI и буквально застреваю на структурировании классов с ведением журнала.
Это правильный способ передать регистратор (или любую другую службу) в подкласс с помощью DI в .NET Core? Согласно приведенному ниже коду, в моем конструкторе родительского класса я беру дополнительный ILogger для каждого подкласса, например.
ILogger<SubClass>?public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)Как мне инициализировать регистратор в моем статическом процессе
StaticProc?public static async Task<bool> StaticProc()
Program.cs:
с использованием Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
с использованием Microsoft.Extensions.Hosting;
с помощью Microsoft.Extensions.Logging;
используя Систему;
используя System.IO;
using System.Threading.Tasks;
пространство имен ConsoleApp1
{
программа класса
{
статическая асинхронная задача Main (строка [] аргументы)
{
var builder = новый ConfigurationBuilder ();
BuildConfig (строитель);
var host = Host.CreateDefaultBuilder ()
.ConfigureServices ((контекст, услуги) =>
{
services.AddTransient <ITestClass, TestClass> ();
services.AddTransient <ISubClass, SubClass> ();
})
.ConfigureLogging (logBuilder =>
{
logBuilder.SetMinimumLevel (LogLevel.Trace);
logBuilder.AddLog4Net ("log4net.config");
})
.Build ();
var log = host.Services.GetService <ILoggerFactory> () .CreateLogger <Program> ();
log.LogInformation ($"Application Started");
var svc = ActivatorUtilities.CreateInstance<TestClass>(host.Services);
await svc.Run();
log.LogInformation($«Заявка завершена»);
}
static void BuildConfig (построитель IConfigurationBuilder)
{
builder.SetBasePath (Directory.GetCurrentDirectory ())
.AddJsonFile ("appsettings.json", необязательно: false, reloadOnChange: true)
.AddJsonFile ($ "appsettings. {Environment.GetEnvironmentVariable (" ASPNETCORE_ENVIRONMENT ") ??" Разработка "}. Json", необязательно: true)
.AddEnvironmentVariables ();
}
}
}
TestClass.cs:
с использованием Microsoft.Extensions.Configuration;
с помощью Microsoft.Extensions.Logging;
using System.Threading.Tasks;
пространство имен ConsoleApp1
{
открытый класс TestClass: ITestClass
{
закрытый только для чтения ILogger <TestClass> _log;
закрытый только для чтения ILogger <SubClass> _subClassLog;
закрытый только для чтения IConfiguration _config;
общедоступный TestClass (журнал ILogger <TestClass>, ILogger <SubClass> subClassLog, конфигурация IConfiguration)
{
_log = журнал;
_subClassLog = subClassLog;
_config = config;
}
общедоступная асинхронная задача Run ()
{
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogDebug ("Отладка цикла {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogInformation ("Информация о цикле {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogWarning ("Предупреждение цикла {номер цикла}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogError ("Ошибка цикла {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogCritical ("Критический цикл {loopNumber}", i);
var subClass = новый подкласс (_subClassLog, _config);
ждать subClass.AnotherProc ();
ждать SubClass.StaticProc ();
}
}
}
SubClass.cs:
с использованием Microsoft.Extensions.Configuration;
с помощью Microsoft.Extensions.Logging;
используя Систему;
using System.Threading.Tasks;
пространство имен ConsoleApp1
{
открытый класс SubClass: ISubClass
{
закрытый только для чтения ILogger <SubClass> _log;
закрытый только для чтения IConfiguration _config;
общедоступный подкласс (журнал ILogger <SubClass>, конфигурация IConfiguration)
{
_log = журнал;
_config = config;
}
общедоступная асинхронная задача AnotherProc ()
{
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogDebug ("Отладка цикла {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogInformation ("Информация о цикле {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogWarning ("Предупреждение цикла {номер цикла}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogError ("Ошибка цикла {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Цикл"); i ++)
_log.LogCritical ("Критический цикл {loopNumber}", i);
}
общедоступная статическая асинхронная задача <bool> StaticProc ()
{
var returnBool = true;
пытаться
{
выбросить новое исключение ("");
}
улов (исключение ex)
{
returnBool = false;
// Нет экземпляра, поэтому нет исключения _log.
// Как создать автономный ILogger?
}
return returnBool;
}
}
}
appsettings.json:
{
«Петля»: 15
}
log4net.config:
<? xml version = "1.0" encoding = "utf-8"?>
<log4net>
<appender name = "Info" type = "log4net.Appender.RollingFileAppender">
<пороговое значение = "DEBUG" />
<param name = "File" value = "App_Data \\ Log \\ Info.log" />
<param name = "AppendToFile" value = "true" />
<maximumFileSize value = "5120 КБ" />
<lockModel type = "log4net.Appender.FileAppender + MinimalLock" />
<maxSizeRollBackups value = "1000" />
<layout type = "log4net.Layout.PatternLayout">
<conversionPattern value = "% d {yyyy-MM-dd HH: mm: ss} - [% t]% -5p% c% x -% m% n" />
</layout>
</appender>
<appender name = "Error" type = "log4net.Appender.RollingFileAppender">
<threshold value = "Ошибка" />
<param name = "File" value = "App_Data \\ Log \\ Error.log" />
<param name = "AppendToFile" value = "true" />
<maximumFileSize value = "5120 КБ" />
<lockModel type = "log4net.Appender.FileAppender + MinimalLock" />
<maxSizeRollBackups value = "1000" />
<layout type = "log4net.Layout.PatternLayout">
<conversionPattern value = "% d {yyyy-MM-dd HH: mm: ss} - [% t]% -5p% c% x -% m% n" />
</layout>
</appender>
<корень>
<appender-ref ref = "Info" />
<appender-ref ref = "Ошибка" />
</root>
</log4net>
Ответы
Резюме
Вы также можете ввести ILoggerFactoryвместо ILogger:
public TestClass(ILoggerFactory loggerFactory, IConfiguration config)
{
// create a class logger
_log = loggerFactory.CreateLogger<TestClass>();
// and whenever you need a new instance of a special class logger use this:
_subClassLog = loggerFactory.Create<SubTestClass>();
_config = config;
}
Но имейте в виду, что это создает новый экземпляр ILogger. Вход в asp net core В вашем случае, если вам действительно нужен статический метод с регистратором, создайте его, только если он уже существует:
private static readonly ILogger<SubClass> _log;
private readonly IConfiguration _config;
public SubClass(ILoggerFactory loggerFactory, IConfiguration config)
{
_log = _log ??= loggerFactory.CreateLogger<SubClass>();
_config = config;
}
Но я предпочту или лучше посоветую вам сделать это без статики и просто зарегистрировать службу как синглтон.
Пример 1
Я добавил здесь полный пример: dotnet fiddle Example 1 Также с рабочим DI для консольных приложений, как указано в комментариях.
Пример 2
Имо, вы должны использовать его не со статическими методами. Просто взгляните на мой второй пример здесь dotnet fiddle Пример 2