.NET Core DI dan sub kelas
Baru mengenal .NET Core di sini. Saya telah mencari dokumentasi, utas, atau panduan lain yang menjawab pertanyaan saya tetapi tidak dapat menemukannya, jika menurut Anda ada, tolong tunjukkan.
Saya mencoba membuat aplikasi konsol .NET 5 sederhana dengan DI dan benar-benar terjebak pada penataan kelas dengan logging.
Apakah ini cara yang benar untuk meneruskan logger (atau layanan lainnya) ke sub kelas menggunakan DI di .NET Core? Sesuai kode di bawah ini, di konstruktor kelas orang tua saya, saya mengambil ILogger ekstra untuk setiap sub kelas misalnya.
ILogger<SubClass>?public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)Bagaimana saya menginisialisasi logger di proc statis saya
StaticProc?public static async Task<bool> StaticProc()
Program.cs:
menggunakan Microsoft.Extensions.Configuration;
menggunakan Microsoft.Extensions.DependencyInjection;
menggunakan Microsoft.Extensions.Hosting;
menggunakan Microsoft.Extensions.Logging;
menggunakan Sistem;
menggunakan System.IO;
menggunakan System.Threading.Tasks;
namespace ConsoleApp1
{
Program kelas
{
statis asinkron Tugas Utama (string [] args)
{
var builder = new ConfigurationBuilder ();
BuildConfig (pembangun);
var host = Host.CreateDefaultBuilder ()
.ConfigureServices ((konteks, layanan) =>
{
services.AddTransient <ITestClass, TestClass> ();
services.AddTransient <ISubClass, SubClass> ();
})
.ConfigureLogging (logBuilder =>
{
logBuilder.SetMinimumLevel (LogLevel.Trace);
logBuilder.AddLog4Net ("log4net.config");
})
.Membangun();
var log = host.Services.GetService <ILoggerFactory> () .CreateLogger <Program> ();
log.LogInformation ($"Application Started");
var svc = ActivatorUtilities.CreateInstance<TestClass>(host.Services);
await svc.Run();
log.LogInformation($"Aplikasi Berakhir");
}
static void BuildConfig (IConfigurationBuilder builder)
{
builder.SetBasePath (Directory.GetCurrentDirectory ())
.AddJsonFile ("appsettings.json", opsional: false, reloadOnChange: true)
.AddJsonFile ($ "appsettings. {Environment.GetEnvironmentVariable (" ASPNETCORE_ENVIRONMENT ") ??" Development "}. Json", opsional: true)
.AddEnvironmentVariables ();
}
}
}
TestClass.cs:
menggunakan Microsoft.Extensions.Configuration;
menggunakan Microsoft.Extensions.Logging;
menggunakan System.Threading.Tasks;
namespace ConsoleApp1
{
kelas publik TestClass: ITestClass
{
pribadi hanya baca ILogger <TestClass> _log;
pribadi hanya baca ILogger <SubClass> _subClassLog;
pribadi IConfiguration _config;
public TestClass (ILogger <TestClass> log, ILogger <SubClass> subClassLog, IConfiguration config)
{
_log = log;
_subClassLog = subClassLog;
_config = config;
}
public async Task Run ()
{
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogDebug ("Ulangi debug {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogInformation ("Loop info {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogWarning ("Loop warn {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogError ("Kesalahan loop {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogCritical ("Loop kritis {loopNumber}", i);
var subClass = new SubClass (_subClassLog, _config);
menunggu subClass.AnotherProc ();
menunggu SubClass.StaticProc ();
}
}
}
SubClass.cs:
menggunakan Microsoft.Extensions.Configuration;
menggunakan Microsoft.Extensions.Logging;
menggunakan Sistem;
menggunakan System.Threading.Tasks;
namespace ConsoleApp1
{
kelas publik SubKelas: ISubClass
{
pribadi hanya baca ILogger <SubClass> _log;
pribadi IConfiguration _config;
Public SubClass (ILogger <SubClass> log, IConfiguration config)
{
_log = log;
_config = config;
}
asinkron publik Tugas AnotherProc ()
{
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogDebug ("Ulangi debug {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogInformation ("Loop info {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogWarning ("Loop warn {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogError ("Kesalahan loop {loopNumber}", i);
untuk (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogCritical ("Loop kritis {loopNumber}", i);
}
public static async Tugas <bool> StaticProc ()
{
var returnBool = true;
mencoba
{
melempar Pengecualian baru ("");
}
catch (Exception ex)
{
returnBool = false;
// Tidak ada contoh, jadi tidak ada pengecualian _log.
// Bagaimana cara membuat ILogger mandiri?
}
return returnBool;
}
}
}
appsettings.json:
{
"Putaran": 15
}
log4net.config:
<? xml version = "1.0" encoding = "utf-8"?>
<log4net>
<appender name = "Info" type = "log4net.Appender.RollingFileAppender">
<nilai ambang = "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">
<nilai conversionPattern = "% d {yyyy-MM-hh JJ: 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">
<nilai conversionPattern = "% d {yyyy-MM-hh JJ: mm: ss} - [% t]% -5p% c% x -% m% n" />
</layout>
</appender>
<root>
<appender-ref ref = "Info" />
<appender-ref ref = "Error" />
</root>
</log4net>
Jawaban
Ringkasan
Anda juga dapat menyuntikkan sebagai ILoggerFactorypengganti 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;
}
Namun ketahuilah bahwa ini membuat instance baru dari ILogger. Masuk dalam asp net core Dalam kasus Anda, jika Anda benar-benar membutuhkan metode statis dengan logger, buat hanya jika sudah ada:
private static readonly ILogger<SubClass> _log;
private readonly IConfiguration _config;
public SubClass(ILoggerFactory loggerFactory, IConfiguration config)
{
_log = _log ??= loggerFactory.CreateLogger<SubClass>();
_config = config;
}
Tapi saya akan lebih suka atau lebih baik saran Anda untuk melakukannya tanpa statika dan hanya mendaftarkan layanan sebagai tunggal.
Contoh 1
Saya menambahkan contoh lengkap di sini: dotnet fiddle Contoh 1 Juga dengan DI yang berfungsi untuk aplikasi konsol seperti yang disebutkan di komentar.
Contoh 2
Imo Anda harus menggunakannya bukan dengan metode statis. Lihat saja contoh kedua saya di sini. Contoh biola dotnet 2