当我谷歌时,我正在寻找有关如何获取泛型类的所有派生类型的答案。但我真正想要的只是通用类的所有变体。
问题是我们在更高的环境中记录了太多信息。我们使用Serilog,我想使用
MinimumLevel.Overide()
方法来根据环境控制日志记录。
为了做到这一点,我需要指定日志记录源。因为应用程序中有很多类型,并且肯定会添加更多类型,所以我想使用反射来查找
ILogger<whatever>
的每个类。
这是一个非常有趣的问题!首先,您想要反映的程序集静态地知道您的所有
ILogger<whatever>
并包含在其元数据中。你不知道确切的类型,你必须遍历所有的程序集类型,包括嵌套类型。最有可能的是,您希望从加载的所有程序集中检索类。
让我们从我们需要使用的库类型开始:
using Type = System.Type;
using TypeList = System.Collections.Generic.List<System.Type>;
using Assembly = System.Reflection.Assembly;
using AppDomain = System.AppDomain;
现在,为了便于说明,让我们在某处定义
ILogger
和一些实现类:
internal interface ILogger<TYPE> {
//...
}
internal class StringLogger : ILogger<string> {
//...
}
internal class TimeLogger : ILogger<System.DateTime> {
//...
}
internal class AssemblyLogger : ILogger<System.Reflection.Assembly> {
//...
}
在您的实际代码中,您将需要使用真正的
ILogger
通用接口,但您将没有有关实现类的信息。让我们找回它们:
static class LoggerClassifier {
static void GetLoggerClasses(Assembly assembly, TypeList collection) {
Type loggerType = typeof(ILogger<>);
Type[] assemblyTypes = assembly.GetTypes();
foreach (var type in assemblyTypes) {
Type[] interfaces = type.GetInterfaces();
foreach (var interfaceInstance in interfaces) {
if (!interfaceInstance.IsGenericType) continue;
if (loggerType == interfaceInstance.GetGenericTypeDefinition())
collection.Add(type);
} //loop
} //loop
} //GetLoggerClasses
internal static Type[] GetLoggerClasses() {
TypeList collection = new();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
GetLoggerClasses(assembly, collection);
return collection.ToArray();
} //GetLoggerClasses
//...
} //class LoggerClassifier
让我们测试一下:
Type[] loggerTypes = LoggerClassifier.GetLoggerClasses();
检查
loggerTypes
,您会发现在当前应用程序域中找到了两个类:StringLogger
、TimeLogger
和AssemblyLogger
。不管怎样,无论您应用到的通用参数ILogger<>
…
就是这样!
谢谢。
—SA