.NET CoreDIおよびサブクラス

Nov 21 2020

ここで.NETCoreの新機能。私の質問に答える別のドキュメント、スレッド、またはガイドを検索しましたが、見つかりません。そうだと思われる場合は、指摘してください。

DIを使用して単純な.NET5コンソールアプリを作成しようとしていますが、文字通り、ロギングを使用したクラスの構造化に行き詰まっています。

  1. これは、.NET CoreのDIを使用してロガー(またはその他のサービス)をサブクラスに渡す正しい方法ですか?以下のコードのように、私の親クラスコンストラクターでは、サブクラスごとに追加のILoggerを使用します。ILogger<SubClass>

    public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)
    
  2. 静的プロシージャでロガーを初期化するにはどうすればよい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
    {{
        クラスプログラム
        {{
            static async Task Main(string [] args)
            {{
                var builder = new ConfigurationBuilder();
                BuildConfig(ビルダー);
    
                var host = Host.CreateDefaultBuilder()
                    .ConfigureServices((context、services)=>
                    {{
                        services.AddTransient <ITestClass、TestClass>();
                        services.AddTransient <ISubClass、SubClass>();
                    })
                    .ConfigureLogging(logBu​​ilder =>
                    {{
                        logBu​​ilder.SetMinimumLevel(LogLevel.Trace);
                        logBu​​ilder.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 ")??" 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 config)
            {{
                _log =ログ;
                _subClassLog = subClassLog;
                _config = config;
            }
    
            public async Task Run()
            {{
                for(int i = 0; i <_config.GetValue <int>( "Loop"); i ++)
                    _log.LogDebug( "Loop debug {loopNumber}"、i);
    
                for(int i = 0; i <_config.GetValue <int>( "Loop"); i ++)
                    _log.LogInformation( "Loop info {loopNumber}"、i);
    
                for(int i = 0; i <_config.GetValue <int>( "Loop"); i ++)
                    _log.LogWarning( "Loop warn {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);
                subClass.AnotherProc();を待つ
    
                SubClass.StaticProc();を待つ
            }
        }
    }

SubClass.cs:

    Microsoft.Extensions.Configurationを使用します。
    Microsoft.Extensions.Loggingを使用する;
    システムを使用する;
    System.Threading.Tasksを使用する;
    
    名前空間ConsoleApp1
    {{
        パブリッククラスサブクラス:ISubClass
        {{
            プライベート読み取り専用ILogger <SubClass> _log;
            プライベート読み取り専用IConfiguration_config;
    
            public SubClass(ILogger <SubClass> log、IConfiguration config)
            {{
                _log =ログ;
                _config = config;
            }
    
            public async Task AnotherProc()
            {{
                for(int i = 0; i <_config.GetValue <int>( "Loop"); i ++)
                    _log.LogDebug( "Loop debug {loopNumber}"、i);
    
                for(int i = 0; i <_config.GetValue <int>( "Loop"); i ++)
                    _log.LogInformation( "Loop info {loopNumber}"、i);
    
                for(int i = 0; i <_config.GetValue <int>( "Loop"); i ++)
                    _log.LogWarning( "Loop warn {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);
            }
    
            public static async Task <bool> StaticProc()
            {{
                var returnBool = true;
    
                試してみてください
                {{
                    新しいException( "");をスローします。
                }
                キャッチ(例外例)
                {{
                    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">
            <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 = "Error" />
            <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 = "Info" />
            <appender-ref ref = "Error" />
        </ root>
    </ log4net>

回答

Martin Nov 21 2020 at 00:13

概要

:の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

ここに完全な例を追加しました。dotnetfiddle例1コメントに記載されているようなコンソールアプリのDIも機能します。

例2

Imo静的メソッドでは使用しないでください。ここで私の2番目の例を見てくださいdotnetfiddle例2