You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射获取所有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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 10:53:11