.NET Core DI 및 하위 클래스
여기서 .NET Core를 처음 사용합니다. 내 질문에 대한 답변을 제공하는 다른 문서, 스레드 또는 가이드를 검색했지만 찾을 수 없습니다. 있다고 생각되면 지적 해주세요.
DI를 사용하여 간단한 .NET 5 콘솔 앱을 만들려고 노력하고 있으며 문자 그대로 로깅을 사용하여 클래스를 구조화하는 데 어려움을 겪고 있습니다.
.NET Core에서 DI를 사용하여 로거 (또는 다른 서비스)를 하위 클래스로 전달하는 올바른 방법입니까? 아래 코드에 따라 부모 클래스 생성자에서 각 하위 클래스에 대해 추가 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 사용; Microsoft.Extensions.DependencyInjection 사용; Microsoft.Extensions.Hosting 사용; Microsoft.Extensions.Logging 사용; 시스템 사용; System.IO 사용; System.Threading.Tasks 사용; 네임 스페이스 ConsoleApp1 { 수업 프로그램 { 정적 비동기 작업 Main (string [] args) { var builder = new 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"); }) .짓다(); 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 ") ??"Development "}. json", 선택 사항 : true) .AddEnvironmentVariables (); } } }
TestClass.cs :
Microsoft.Extensions.Configuration 사용; Microsoft.Extensions.Logging 사용; System.Threading.Tasks 사용; 네임 스페이스 ConsoleApp1 { 공용 클래스 TestClass : ITestClass { 개인 읽기 전용 ILogger <TestClass> _log; 개인 읽기 전용 ILogger <SubClass> _subClassLog; 개인 읽기 전용 IConfiguration _config; public TestClass (ILogger <TestClass> 로그, ILogger <SubClass> subClassLog, IConfiguration 구성) { _log = 로그; _subClassLog = subClassLog; _config = 구성; } 공용 비동기 작업 Run () { for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogDebug ( "루프 디버그 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogInformation ( "루프 정보 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogWarning ( "루프 경고 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogError ( "루프 오류 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogCritical ( "루프 임계 {loopNumber}", i); var subClass = new SubClass (_subClassLog, _config); await subClass.AnotherProc (); await SubClass.StaticProc (); } } }
SubClass.cs :
Microsoft.Extensions.Configuration 사용; Microsoft.Extensions.Logging 사용; 시스템 사용; System.Threading.Tasks 사용; 네임 스페이스 ConsoleApp1 { 공용 클래스 SubClass : ISubClass { 개인 읽기 전용 ILogger <SubClass> _log; 개인 읽기 전용 IConfiguration _config; public SubClass (ILogger <SubClass> 로그, IConfiguration 구성) { _log = 로그; _config = 구성; } 공용 비동기 작업 AnotherProc () { for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogDebug ( "루프 디버그 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogInformation ( "루프 정보 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogWarning ( "루프 경고 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogError ( "루프 오류 {loopNumber}", i); for (int i = 0; i <_config.GetValue <int> ( "Loop"); i ++) _log.LogCritical ( "루프 임계 {loopNumber}", i); } 공용 정적 비동기 태스크 <bool> StaticProc () { var returnBool = true; 시험 { throw new Exception ( ""); } catch (예외) { returnBool = 거짓; // 인스턴스가 없으므로 _log 예외가 없습니다. // 독립형 ILogger를 만드는 방법은 무엇입니까? } return returnBool; } } }
appsettings.json :
{ "루프": 15 }
log4net.config :
<? xml version = "1.0"encoding = "utf-8"?> <log4net> <appender name = "Info"type = "log4net.Appender.RollingFileAppender"> <threshold value = "DEBUG"/> <param name = "File"value = "App_Data \\ Log \\ Info.log"/> <param name = "AppendToFile"value = "true"/> <maximumFileSize value = "5120KB"/> <lockingModel 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"/> </ 레이아웃> </ 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 = "5120KB"/> <lockingModel 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"/> </ 레이아웃> </ appender> <루트> <appender-ref ref = "정보"/> <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 예제 1 주석에서 언급 한 것과 같은 콘솔 앱에 대해 작동하는 DI도 있습니다.
예 2
이모는 정적 메서드와 함께 사용하지 않아야합니다. 여기 내 두 번째 예제를보십시오. dotnet fiddle 예제 2