.NET Core DI e sottoclassi
Novità di .NET Core qui. Ho cercato un'altra documentazione, thread o guida che rispondesse alle mie domande ma non riesco a trovarne uno, se pensi che lo faccia, ti preghiamo di segnalarlo.
Sto cercando di creare una semplice app console .NET 5 con DI e rimango letteralmente bloccato sulla strutturazione delle classi con la registrazione.
È questo il modo corretto per passare un logger (o qualsiasi altro servizio) a una sottoclasse utilizzando DI in .NET Core? Come da codice seguente, nel costruttore della mia classe genitore prendo un ILogger extra per ogni sottoclasse, ad es.
ILogger<SubClass>?public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)Come potrei inizializzare un logger nel mio processo statico
StaticProc?public static async Task<bool> StaticProc()
Program.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;
spazio dei nomi ConsoleApp1
{
programma di classe
{
attività asincrona statica principale (string [] args)
{
var builder = new ConfigurationBuilder ();
BuildConfig (generatore);
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");
})
.Costruire();
var log = host.Services.GetService <ILoggerFactory> () .CreateLogger <Program> ();
log.LogInformation ($"Application Started");
var svc = ActivatorUtilities.CreateInstance<TestClass>(host.Services);
await svc.Run();
log.LogInformation($"Applicazione terminata");
}
static void BuildConfig (IConfigurationBuilder builder)
{
builder.SetBasePath (Directory.GetCurrentDirectory ())
.AddJsonFile ("appsettings.json", facoltativo: false, reloadOnChange: true)
.AddJsonFile ($ "appsettings. {Environment.GetEnvironmentVariable (" ASPNETCORE_ENVIRONMENT ") ??" Development "}. Json", opzionale: true)
.AddEnvironmentVariables ();
}
}
}
TestClass.cs:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
spazio dei nomi ConsoleApp1
{
classe pubblica TestClass: ITestClass
{
privato in sola lettura ILogger <TestClass> _log;
privato in sola lettura 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 ("Errore di ciclo {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogCritical ("Loop critico {loopNumber}", i);
var subClass = new SubClass (_subClassLog, _config);
attende subClass.AnotherProc ();
attende SubClass.StaticProc ();
}
}
}
Sottoclasse.cs:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
spazio dei nomi ConsoleApp1
{
classe pubblica Sottoclasse: ISubClass
{
privato in sola lettura 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 ("Errore di ciclo {loopNumber}", i);
for (int i = 0; i <_config.GetValue <int> ("Loop"); i ++)
_log.LogCritical ("Loop critico {loopNumber}", i);
}
public static async Task <bool> StaticProc ()
{
var returnBool = true;
provare
{
lancia una nuova eccezione ("");
}
cattura (eccezione ex)
{
returnBool = false;
// Nessuna istanza, quindi nessuna eccezione _log.
// Come creare ILogger autonomo?
}
return returnBool;
}
}
}
appsettings.json:
{
"Loop": 15
}
log4net.config:
<? xml version = "1.0" encoding = "utf-8"?>
<log4net>
<appender name = "Info" type = "log4net.Appender.RollingFileAppender">
<valore soglia = "DEBUG" />
<param name = "File" value = "App_Data \\ Log \\ Info.log" />
<param name = "AppendToFile" value = "true" />
<valore maximumFileSize = "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">
<valore soglia = "Errore" />
<param name = "File" value = "App_Data \\ Log \\ Error.log" />
<param name = "AppendToFile" value = "true" />
<valore maximumFileSize = "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 = "Errore" />
</root>
</log4net>
Risposte
Sommario
Puoi anche iniettare un ILoggerFactoryinvece di 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;
}
Ma tieni presente che questo crea una nuova istanza di ILogger. Accesso ad asp net core Nel tuo caso, se hai davvero bisogno del metodo statico con un logger, crealo solo se esiste già:
private static readonly ILogger<SubClass> _log;
private readonly IConfiguration _config;
public SubClass(ILoggerFactory loggerFactory, IConfiguration config)
{
_log = _log ??= loggerFactory.CreateLogger<SubClass>();
_config = config;
}
Ma preferirò o meglio consigliarti di farlo senza avere statistiche e registrare il servizio come singleton.
Esempio 1
Ho aggiunto un esempio completo qui: dotnet fiddle Esempio 1 Anche con il DI funzionante per le app della console come menzionato nei commenti.
Esempio 2
Imo dovresti usarlo non con metodi statici. Basta guardare al mio secondo esempio qui dotnet fiddle Esempio 2