[英].NET Core DI and sub classes
.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()
程序.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;
}
但是我會更喜歡或更好地建議您在沒有靜態的情況下執行此操作,只需將服務注冊為單例即可。
我在這里添加了一個完整的示例: dotnet fiddle Example 1還包括評論中提到的控制台應用程序的工作 DI。
我不應該將它與靜態方法一起使用。 看看我的第二個例子dotnet fiddle Example 2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.