Nous avons des classes BL communes dans une application ASP.NET Core qui arrivent dans le ctor:
Microsoft.Extensions.Logging.ILogger<Foo>
Dans ASP.NET Core, l'infrastructure interne d'ASP.NET gère l'obtention de l'ILogger via le LoggerFactory
.
Nous voulons maintenant réutiliser ces classes BL dans une application console (pour les tâches asynchrones), comment configurer AutoFac et Serilog pour injecter Microsoft.Extensions.Logging.ILogger<T>
dans un environnement qui n'existe pas LoggerFactory
?
Microsoft.Extensions.Logging
(voir source ) ne fait pas partie d'ASP.NET Core et peut fonctionner indépendamment de lui. Tout ce que vous avez à faire est d'enregistrer les ILoggerFactory
et ILogger<>
interface.
ILoggerFactory
est utilisé parLogger<T>
pour instancier l'enregistreur réel.
Lorsque vous utilisez l'extension Logging dans les applications de console, il est toujours recommandé d'utiliser le IServiceCollection
, car cela vous permet d'utiliser le IServiceCollection
méthodes d'extension pour enregistrer tous les packages qui prennent en charge ce modèle.
var services = new ServiceCollection();
services.AddLogging();
// Initialize Autofac
var builder = new ContainerBuilder();
// Use the Populate method to register services which were registered
// to IServiceCollection
builder.Populate(services);
// Build the final container
IContainer container = builder.Build();
C'est l'approche recommandée, car vous n'aurez pas à penser en détail quelles classes doivent être enregistrées pour les bibliothèques qui ont Microsoft.Extensions.DependencyInjection
support d'intégration.
Mais bien sûr, vous pouvez également l'enregistrer manuellement, mais lorsqu'un changement se produit dans le Microsoft.Extensions.Logging
bibliothèque (nouvelle dépendance ajoutée), vous ne l'obtiendrez pas et devez d'abord comprendre ou Dig dans le code source pour trouver l'erreur.
builder.RegisterType<LoggerFactory>()
.As<ILoggerFactory>()
.SingleInstance();
builder.RegisterGeneric(typeof(Logger<>))
.As(typeof(ILogger<>))
.SingleInstance();
Il ne reste plus qu'à enregistrer les types d'enregistreurs après la construction du conteneur ou avant le démarrage de votre application:
var loggerFactory = container.Resolve<ILoggerFactory>();
loggerFactory.AddConsole()
.AddSerilog();
et dans vos services injectez ILogger<MyService>
comme d'habitude.
Je recommanderais une approche légèrement différente si vous souhaitez vous inscrire manuellement directement sur Autofac:
private static void ConfigureLogging(ILoggingBuilder log)
{
log.ClearProviders();
log.SetMinimumLevel(LogLevel.Error);
log.AddConsole();
}
private static void ConfigureContainer(ContainerBuilder builder)
{
builder.Register(handler => LoggerFactory.Create(ConfigureLogging))
.As<ILoggerFactory>()
.SingleInstance()
.AutoActivate();
builder.RegisterGeneric(typeof(Logger<>))
.As(typeof(ILogger<>))
.SingleInstance();
// other registrations
}
Et cela sur votre code de démarrage principal:
var containerBuilder = new ContainerBuilder();
ConfigureContainer(containerBuilder);
var container = containerBuilder.Build();
var serviceProvider = new AutofacServiceProvider(container);
// you can use either the built container or set the serviceProvider onto the library you are using.
Dans la méthode principale de l'application Console
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
IConfigurationRoot configuration = builder.Build();
var serviceProvider = new ServiceCollection()
.AddDbContext<MyDbContext>(optionns => optionns.UseSqlServer(configuration.GetConnectionString("connectionString")))
.AddSingleton(typeof(ILogger<>), typeof(Logger<>))
.AddLogging()
.BuildServiceProvider();
MyDbContext _context = serviceProvider.GetService<MyDbContext>();
var _logger = serviceProvider.GetService<ILogger<YourClass>>();