如何通过反射获取所有ILogger<任意类型>的泛型类型?
用反射批量获取ILogger泛型参数并配置Serilog日志级别覆盖
核心思路
你需要的不是ILogger<>的派生类,而是所有被用作ILogger<T>泛型参数的T类型——因为Serilog中ILogger<T>的日志源默认是T的完整类型名,通过反射批量提取这些T类型,就能自动完成MinimumLevel.Override()的配置,无需手动维护新增类型。
实现代码
using System.Reflection; using Microsoft.Extensions.Logging; using Serilog; // 获取当前应用域加载的所有程序集 var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); // 定义ILogger<>的泛型模板类型 var loggerGenericDefinition = typeof(ILogger<>); // 筛选所有ILogger<T>实例对应的T类型,并去重 var allLoggerTargetTypes = loadedAssemblies .SelectMany(asm => asm.GetTypes()) .Where(type => type.IsGenericType && type.GetGenericTypeDefinition() == loggerGenericDefinition) .Select(type => type.GetGenericArguments()[0]) .Distinct(); // 初始化Serilog配置 var logConfig = new LoggerConfiguration() .MinimumLevel.Information() // 默认全局日志级别 .Enrich.FromLogContext(); // 根据环境变量设置目标日志级别 var targetLevel = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production" ? LogEventLevel.Warning : LogEventLevel.Information; // 批量配置日志级别覆盖 foreach (var targetType in allLoggerTargetTypes) { logConfig.MinimumLevel.Override(targetType.FullName, targetLevel); } // 创建Logger实例 var logger = logConfig.CreateLogger();
关键细节
- 程序集过滤:如果不需要处理第三方库的
ILogger<T>,可以在遍历程序集时添加过滤条件,比如排除系统或微软官方程序集:.Where(asm => !asm.FullName.StartsWith("System.") && !asm.FullName.StartsWith("Microsoft.")) - 动态程序集处理:如果应用存在动态加载的程序集,需要订阅
AppDomain.CurrentDomain.AssemblyLoad事件,在程序集加载后重新执行上述逻辑。 - 去重逻辑:
Distinct()确保同一个T类型不会被重复配置,避免冗余。
内容的提问来源于stack exchange,提问作者BVernon
相关产品推荐
相关产品推荐

