如何实现ILoggerFactory?自定义工厂配置与调用方法咨询
按名称指定日志提供程序的实现方案
1. 实现自定义ILoggerFactory:MyFactory
需要实现ILoggerFactory接口,同时维护日志提供程序与名称的映射关系,核心是根据指定名称找到对应Provider创建日志实例。
using Microsoft.Extensions.Logging; using System.Collections.Concurrent; using System.Linq; public class MyFactory : ILoggerFactory { private readonly ConcurrentDictionary<string, ILoggerProvider> _providerMap = new(); private bool _disposed = false; // 构造函数注入所有已注册的日志提供程序,并绑定名称 public MyFactory(IEnumerable<ILoggerProvider> providers) { foreach (var provider in providers) { // 按Provider类型关联名称,也可以根据Provider自定义的Name属性绑定 var providerName = provider.GetType().Name; _providerMap.TryAdd(providerName, provider); } } // 实现接口要求的默认CreateLogger方法 public ILogger CreateLogger(string categoryName) { // 返回第一个注册的Provider实例,或根据业务需求调整默认逻辑 return _providerMap.Values.First().CreateLogger(categoryName); } // 自定义泛型方法:按类型分类+指定Provider名称创建日志 public ILogger<T> CreateLogger<T>(string providerName) { if (!_providerMap.TryGetValue(providerName, out var targetProvider)) throw new ArgumentException($"未找到名为 {providerName} 的日志提供程序"); return new LoggerWrapper<T>(targetProvider.CreateLogger(typeof(T).FullName)); } public void AddProvider(ILoggerProvider provider) { var providerName = provider.GetType().Name; _providerMap.TryAdd(providerName, provider); } public void Dispose() { if (_disposed) return; foreach (var provider in _providerMap.Values) provider.Dispose(); _disposed = true; } // 泛型日志包装类,适配ILogger<T>接口 private class LoggerWrapper<T> : ILogger<T> { private readonly ILogger _innerLogger; public LoggerWrapper(ILogger innerLogger) { _innerLogger = innerLogger; } public IDisposable BeginScope<TState>(TState state) => _innerLogger.BeginScope(state); public bool IsEnabled(LogLevel logLevel) => _innerLogger.IsEnabled(logLevel); public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) => _innerLogger.Log(logLevel, eventId, state, exception, formatter); } }
如果不想在MyFactory内定义泛型方法,也可以通过扩展方法实现:
public static class LoggerFactoryExtensions { public static ILogger<T> CreateLogger<T>(this ILoggerFactory factory, string providerName) { if (factory is not MyFactory myFactory) throw new InvalidOperationException("当前LoggerFactory不是自定义的MyFactory实例"); return myFactory.CreateLogger<T>(providerName); } }
2. 在Program.cs中加载MyFactory
替换默认的ILoggerFactory注册,确保自定义工厂能获取到已注册的日志提供程序:
var builder = WebApplication.CreateBuilder(args); // 注册日志提供程序(保留原有逻辑) builder.Services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); loggingBuilder.AddProvider(new LoggerProvider1()); loggingBuilder.AddProvider(new LoggerProvider2()); }); // 替换默认LoggerFactory为自定义MyFactory builder.Services.AddSingleton<ILoggerFactory, MyFactory>(); // 其他服务注册逻辑... var app = builder.Build(); // 应用启动逻辑... app.Run();
3. 调用ILoggerFactory获取指定Provider的日志实例
在需要的类中注入ILoggerFactory,直接调用自定义方法获取对应Provider的日志实例:
public class HomeController : Controller { private readonly ILogger<HomeController> _loggerFromProvider1; private readonly ILogger<HomeController> _loggerFromProvider2; public HomeController(ILoggerFactory factory) { // 按名称指定Provider获取日志实例 _loggerFromProvider1 = factory.CreateLogger<HomeController>("LoggerProvider1"); _loggerFromProvider2 = factory.CreateLogger<HomeController>("LoggerProvider2"); } public IActionResult Index() { _loggerFromProvider1.LogInformation("通过LoggerProvider1记录的日志"); _loggerFromProvider2.LogInformation("通过LoggerProvider2记录的日志"); return View(); } }
内容的提问来源于stack exchange,提问作者mayi
相关产品推荐
相关产品推荐

