【问题标题】:Find all classes with a specific attribut [duplicate]查找具有特定属性的所有类[重复]
【发布时间】:2013-01-04 14:45:03
【问题描述】:

可能重复:
Finding all classes with a particular attribute

在程序集中,我想获取特定类属性的所有实例。换句话说,我想拥有具有特定属性的类列表。

通常你会有一个可以使用GetCustomAttributes 方法获取属性的类。

是否有可能列出谁具有特定属性?

【问题讨论】:

  • 您是指程序集中具有特定属性的类列表吗?您在什么范围内获得课程列表?
  • 致所有投反对票的人!请留下您的反对票。

标签: c# attributes


【解决方案1】:
public static IEnumerable<Type> GetTypesWithMyAttribute(Assembly assembly)
{
    foreach(Type type in assembly.GetTypes())
    {
        if (Attribute.IsDefined(type, typeof(MyAttribute)))
            yield return type;
    }
}

或者:

public static List<Type> GetTypesWithMyAttribute(Assembly assembly)
{
    List<Type> types = new List<Type>();

    foreach(Type type in assembly.GetTypes())
    {
        if (type.GetCustomAttributes(typeof(MyAttribute), true).Length > 0)
            types.Add(type);
    }

    return types;
}

Linq VS 我的方法基准(100000 次迭代):

Round 1
My Approach:     2088ms
Linq Approach 1: 7469ms
Linq Approach 2: 2514ms

Round 2
My Approach:     2055ms
Linq Approach 1: 7082ms
Linq Approach 2: 2149ms

Round 3
My Approach:     2058ms
Linq Approach 1: 7001ms
Linq Approach 2: 2249ms

基准代码:

[STAThread]
public static void Main()
{
    List<Type> list;

    Stopwatch watch = Stopwatch.StartNew();

    for (Int32 i = 0; i < 100000; ++i)
        list = GetTypesWithMyAttribute(Assembly.GetExecutingAssembly());

    watch.Stop();

    Console.WriteLine("ForEach: " + watch.ElapsedMilliseconds);

    watch.Restart();

    for (Int32 i = 0; i < 100000; ++i)
        list = GetTypesWithMyAttributeLinq1(Assembly.GetExecutingAssembly());

    Console.WriteLine("Linq 1: " + watch.ElapsedMilliseconds);

    watch.Restart();

    for (Int32 i = 0; i < 100000; ++i)
        list = GetTypesWithMyAttributeLinq2(Assembly.GetExecutingAssembly());

    Console.WriteLine("Linq 2: " + watch.ElapsedMilliseconds);

    Console.Read();
}

public static List<Type> GetTypesWithMyAttribute(Assembly assembly)
{
    List<Type> types = new List<Type>();

    foreach (Type type in assembly.GetTypes())
    {
        if (Attribute.IsDefined(type, typeof(MyAttribute)))
            types.Add(type);
    }

    return types;
}

public static List<Type> GetTypesWithMyAttributeLinq1(Assembly assembly)
{
    return assembly.GetTypes()
               .Where(t => t.GetCustomAttributes().Any(a => a is MyAttribute))
               .ToList();
}

public static List<Type> GetTypesWithMyAttributeLinq2(Assembly assembly)
{
    return assembly.GetTypes()
               .Where(t => Attribute.IsDefined(t, typeof(MyAttribute)))
               .ToList();
}

【讨论】:

  • 使用 LINQ 可能会加快速度,而不是循环遍历类,但仍然可以达到相同的结果:)
  • 我们来试试基准吧!
  • 伙计们,我对这里的速度不感兴趣。清晰度是我所关心的。我只会在整个应用程序中执行一次。无论如何,谢谢你的努力。
  • 基准测试完成。 Linq 不能比经典迭代更快。
  • 是的,但仍然是 O(1),我可以告诉你我的程序集不是也不应该很大。 :)
【解决方案2】:

没有代码示例,假设您有List&lt;Type&gt;Assembly

public List<Type> TypesWithAttributeDefined(Type attribute)
{
  List<Type> types = assembly.GetTypes();
  return types.Where(t => Attribute.IsDefined(t, attribute)).ToList();
}

【讨论】:

    【解决方案3】:

    您可以使用reflection 执行此操作。这将为您提供当前程序集中具有MyAttribute 的所有类型的List&lt;Type&gt;

    using System.Linq;
    using System.Reflection;
    
    // ...
    
    var asmbly = Assembly.GetExecutingAssembly();
    var typeList = asmbly.GetTypes().Where(
            t => t.GetCustomAttributes(typeof (MyAttribute), true).Length > 0
    ).ToList();
    

    【讨论】:

    • 是的,这就是我想要避免的。必须遍历特定程序集的所有类并不是很好。但如果这是唯一的解决方案。
    • @mathk 不幸的是;不过,执行每种类型的检查不应该那么慢。如果您要在多个地方重复使用此检查,您可以随时缓存结果。
    • 我只会在应用程序开始时使用它一次。我不关心速度。但是要求运行时创建所有内容确实会具体化,这是我不太喜欢的事情。 Attribute 类上的一些静态方法,例如:GetAllType,或GetAllProperties,...会更好。
    • @mathk 我明白了,但如果你只是在启动时运行它,它可能不是那么大的性能问题 :) 顺便说一句,你总是可以实现这个仍然最终使用的静态方法这段代码作为后盾。你想要一个例子吗?
    • 是的,你是正确的,速度不是问题。我发现的小缺点是:就像您必须对心脏进行手术,但在其他情况下要到达心脏,您必须扫描所有其他器官。它不是很干净,没有双关语。如果反射不被允许,因为它暴露了太多的运行时细节。
    【解决方案4】:
    var list = asm.GetTypes()
                .Where(t => t.GetCustomAttributes().Any(a => a is YourAttribute))
                .ToList();
    

    【讨论】:

      猜你喜欢
      • 2010-10-17
      • 1970-01-01
      • 2018-04-29
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      • 2021-05-19
      相关资源
      最近更新 更多