如何枚举具有自定义类属性的所有类?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (25)

基于MSDN示例的问题

假设我们在独立桌面应用程序中有一些带有HelpAttribute的C#类。有没有可能枚举具有这种属性的所有类?以这种方式识别班级有意义吗?自定义属性将用于列出可能的菜单选项,选择项目将带来此类的实例。类/项目的数量将会增长缓慢,但这样我们可以避免在其他地方列举它们,我想。

提问于
用户回答回答于

是的,一点没错。使用反射:

static IEnumerable<Type> GetTypesWithHelpAttribute(Assembly assembly) {
    foreach(Type type in assembly.GetTypes()) {
        if (type.GetCustomAttributes(typeof(HelpAttribute), true).Length > 0) {
            yield return type;
        }
    }
}
用户回答回答于

那么,你将不得不枚举所有加载到当前应用程序域的程序集中的所有类。要做到这一点,您需要在当前应用程序域的实例上调用该GetAssemblies方法AppDomain

从那里,你可以调用GetExportedTypes(如果你只需要公共类型)或者GetTypes每个Assembly类型来获取程序集中包含的类型。

然后,您将在每个实例上调用该GetCustomAttributes方法Type,传递您希望查找的属性的类型。

你可以使用LINQ来为你简化它:

var typesWithMyAttribute =
    from a in AppDomain.CurrentDomain.GetAssemblies()
    from t in a.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

上面的查询将为您提供应用于它的每个类型的属性以及分配给它的属性的实例。

请注意,如果您将大量程序集加载到应用程序域中,那么该操作可能很昂贵。您可以使用Parallel LINQ来减少操作的时间,如下所示:

var typesWithMyAttribute =
    // Note the AsParallel here, this will parallelize everything after.
    from a in AppDomain.CurrentDomain.GetAssemblies().AsParallel()
    from t in a.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

过滤一个特定的Assembly很简单:

Assembly assembly = ...;

var typesWithMyAttribute =
    from t in assembly.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

如果程序集中有大量的类型,那么你可以再次使用Parallel LINQ:

Assembly assembly = ...;

var typesWithMyAttribute =
    // Partition on the type list initially.
    from t in assembly.GetTypes().AsParallel()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

扫码关注云+社区