簡體   English   中英

.NET Core DI 和子類

[英].NET Core DI and sub classes

.NET Core 的新手在這里。 我已經搜索了另一個文檔、線程或指南來回答我的問題,但找不到,如果您認為有,請指出。

我正在嘗試使用 DI 創建一個簡單的 .NET 5 控制台應用程序,並且實際上陷入了使用日志記錄結構化類的問題。

  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()

程序.cs:

using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using System;
    using System.IO;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static async Task Main(string[] args)
            {
                var builder = new ConfigurationBuilder();
                BuildConfig(builder);
    
                var host = Host.CreateDefaultBuilder()
                    .ConfigureServices((context, services) =>
                    {
                        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($"Application Ended");
            }
    
            static void BuildConfig(IConfigurationBuilder builder)
            {
                builder.SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"}.json", optional: true)
                    .AddEnvironmentVariables();
            }
        }
    }

測試類.cs:

using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        public class TestClass : ITestClass
        {
            private readonly ILogger<TestClass> _log;
            private readonly ILogger<SubClass> _subClassLog;
            private readonly IConfiguration _config;
    
            public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)
            {
                _log = 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("Loop error {loopNumber}", i);
    
                for (int i = 0; i < _config.GetValue<int>("Loop"); i++)
                    _log.LogCritical("Loop critical {loopNumber}", i);
    
                var subClass = new SubClass(_subClassLog, _config);
                await subClass.AnotherProc();
    
                await SubClass.StaticProc();
            }
        }
    }

子類.cs:

using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    using System;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        public class SubClass : ISubClass
        {
            private readonly ILogger<SubClass> _log;
            private readonly IConfiguration _config;
    
            public SubClass(ILogger<SubClass> log, IConfiguration config)
            {
                _log = 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("Loop error {loopNumber}", i);
    
                for (int i = 0; i < _config.GetValue<int>("Loop"); i++)
                    _log.LogCritical("Loop critical {loopNumber}", i);
            }
    
            public static async Task<bool> StaticProc()
            {
                var returnBool = true;
    
                try
                {
                    throw new Exception("");
                }
                catch (Exception ex)
                {
                    returnBool = false;
    
                    // No instance, so no _log exception.
                    // How to create standalone ILogger?
                }
    
                return returnBool;
            }
        }
    }

appsettings.json:

{
      "Loop": 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" />
            </layout>
        </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" />
            </layout>
        </appender>
        <root>
            <appender-ref ref="Info" />
            <appender-ref ref="Error" />
        </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 Example 2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM