.NET Core DI y subclases
Nuevo en .NET Core aquí. He buscado otra documentación, hilo o guía que responda a mis preguntas, pero no puedo encontrar uno, si cree que lo hace, por favor indíquelo.
Estoy tratando de crear una aplicación de consola .NET 5 simple con DI y, literalmente, me quedo atascado en la estructuración de clases con registro.
¿Es esta la forma correcta de pasar un registrador (o cualquier otro servicio) a una subclase usando DI en .NET Core? Según el código siguiente, en el constructor de mi clase principal, tomo un ILogger adicional para cada subclase, por ejemplo.
ILogger<SubClass>?public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)¿Cómo inicializaría un registrador en mi proceso estático
StaticProc?public static async Task<bool> StaticProc()
Program.cs:
utilizando Microsoft.Extensions.Configuration;
utilizando Microsoft.Extensions.DependencyInjection;
utilizando Microsoft.Extensions.Hosting;
utilizando Microsoft.Extensions.Logging;
usando el sistema;
usando System.IO;
usando System.Threading.Tasks;
espacio de nombres ConsoleApp1
{
programa de clase
{
estática asíncrona tarea principal (cadena [] argumentos)
{
var builder = new ConfigurationBuilder ();
BuildConfig (constructor);
var host = Host.CreateDefaultBuilder ()
.ConfigureServices ((contexto, servicios) =>
{
services.AddTransient <ITestClass, TestClass> ();
services.AddTransient <ISubClass, SubClass> ();
})
.ConfigureLogging (logBuilder =>
{
logBuilder.SetMinimumLevel (LogLevel.Trace);
logBuilder.AddLog4Net ("log4net.config");
})
.Construir();
var log = host.Services.GetService <ILoggerFactory> () .CreateLogger <Program> ();
log.LogInformation ($"Application Started");
var svc = ActivatorUtilities.CreateInstance<TestClass>(host.Services);
await svc.Run();
log.LogInformation($"Solicitud finalizada");
}
static void BuildConfig (constructor IConfigurationBuilder)
{
constructor.SetBasePath (Directory.GetCurrentDirectory ())
.AddJsonFile ("appsettings.json", opcional: falso, reloadOnChange: verdadero)
.AddJsonFile ($ "appsettings. {Environment.GetEnvironmentVariable (" ASPNETCORE_ENVIRONMENT ") ??" Development "}. Json", opcional: verdadero)
.AddEnvironmentVariables ();
}
}
}
TestClass.cs:
utilizando Microsoft.Extensions.Configuration;
utilizando Microsoft.Extensions.Logging;
usando System.Threading.Tasks;
espacio de nombres ConsoleApp1
{
clase pública TestClass: ITestClass
{
privado de solo lectura ILogger <TestClass> _log;
privado de solo lectura ILogger <SubClass> _subClassLog;
IConfiguration _config privado de solo lectura;
Public TestClass (ILogger <TestClass> registro, ILogger <SubClass> subClassLog, IConfiguration config)
{
_log = registro;
_subClassLog = subClassLog;
_config = config;
}
ejecución de tarea asíncrona pública ()
{
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogDebug ("Loop debug {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogInformation ("Información de bucle {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogWarning ("Advertencia de bucle {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogError ("Error de bucle {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogCritical ("Loop crítico {loopNumber}", i);
var subClass = new SubClass (_subClassLog, _config);
esperar subClass.AnotherProc ();
espera SubClass.StaticProc ();
}
}
}
SubClass.cs:
utilizando Microsoft.Extensions.Configuration;
utilizando Microsoft.Extensions.Logging;
usando el sistema;
usando System.Threading.Tasks;
espacio de nombres ConsoleApp1
{
clase pública Subclase: ISubClass
{
privado de solo lectura ILogger <SubClass> _log;
IConfiguration _config privado de solo lectura;
subclase pública (registro ILogger <SubClass>, configuración de IConfiguration)
{
_log = registro;
_config = config;
}
Tarea asíncrona pública AnotherProc ()
{
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogDebug ("Loop debug {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogInformation ("Información de bucle {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogWarning ("Advertencia de bucle {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogError ("Error de bucle {loopNumber}", i);
para (int i = 0; i <_config.GetValue <int> ("Bucle"); i ++)
_log.LogCritical ("Loop crítico {loopNumber}", i);
}
Tarea asíncrona estática pública <bool> StaticProc ()
{
var returnBool = true;
tratar
{
lanzar una nueva excepción ("");
}
catch (Excepción ex)
{
returnBool = falso;
// Sin instancia, por lo que no hay excepción _log.
// ¿Cómo crear ILogger independiente?
}
return returnBool;
}
}
}
appsettings.json:
{
"Bucle": 15
}
log4net.config:
<? xml version = "1.0" encoding = "utf-8"?>
<log4net>
<appender name = "Info" type = "log4net.Appender.RollingFileAppender">
<valor umbral = "DEPURACIÓN" />
<param name = "File" value = "App_Data \\ Log \\ Info.log" />
<param name = "AppendToFile" value = "true" />
<maximumFileSize value = "5120KB" />
<lockModel type = "log4net.Appender.FileAppender + MinimalLock" />
<maxSizeRollBackups value = "1000" />
<layout type = "log4net.Layout.PatternLayout">
<conversionPattern value = "% d {aaaa-MM-dd HH: mm: ss} - [% t]% -5p% c% x -% m% n" />
</layout>
</appender>
<appender name = "Error" type = "log4net.Appender.RollingFileAppender">
<valor de umbral = "Error" />
<param name = "File" value = "App_Data \\ Log \\ Error.log" />
<param name = "AppendToFile" value = "true" />
<maximumFileSize value = "5120KB" />
<lockModel type = "log4net.Appender.FileAppender + MinimalLock" />
<maxSizeRollBackups value = "1000" />
<layout type = "log4net.Layout.PatternLayout">
<conversionPattern value = "% d {aaaa-MM-dd HH: mm: ss} - [% t]% -5p% c% x -% m% n" />
</layout>
</appender>
<raíz>
<appender-ref ref = "Información" />
<appender-ref ref = "Error" />
</root>
</log4net>
Respuestas
Resumen
También puede inyectar a en ILoggerFactorylugar de 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;
}
Pero tenga en cuenta que esto crea una nueva instancia de ILogger. Iniciar sesión en asp net core En su caso, si realmente necesita el método estático con un registrador, créelo solo si ya existe:
private static readonly ILogger<SubClass> _log;
private readonly IConfiguration _config;
public SubClass(ILoggerFactory loggerFactory, IConfiguration config)
{
_log = _log ??= loggerFactory.CreateLogger<SubClass>();
_config = config;
}
Pero preferiré o le aconsejaré mejor que lo haga sin tener estática y simplemente registre el servicio como singleton.
Ejemplo 1
Agregué un ejemplo completo aquí: dotnet fiddle Example 1 También con la DI de trabajo para aplicaciones de consola como se menciona en los comentarios.
Ejemplo 2
Imo no deberías usarlo con métodos estáticos. Solo mira mi segundo ejemplo aquí dotnet violín Ejemplo 2