反思:如何创建精确过滤的程序集类型列表?

时间:2015-07-21 04:37:55

标签: c# reflection types

foreach (var item in Assembly.GetExecutingAssembly().GetTypes()
                             .Where(x => x.BaseType == typeof(Item)))
{
    comboBox1.Items.Add(item);
}
comboBox1.DisplayMember = "Name";

是否可以对其进行修改,以便列表中包含派生自' Item'的所有类。即使他们被删除了两次或更多次? (即:x.BaseType.BaseType == typeof(Item)等。)

此外,是否可以过滤掉所有抽象类?

2 个答案:

答案 0 :(得分:2)

一个简单的方法是使用IsAssignableFrom

foreach (var item in Assembly.GetExecutingAssembly().GetTypes()
                             .Where(x => typeof(Item).IsAssignableFrom(x) && !x.IsAbstract))
{
    //Handle each item
}

假设我的" Handle每个项目都是Console.WriteLine(item),我有这个类结构:

class ItemBase {}
class Item : ItemBase {}
class SuperItem : Item {}
abstract class SuperSuperItem : SuperItem{}
class UltimateItem : SuperSuperItem {}

输出结果为:

  

项目

     

SuperItem

     

UltimateItem

请注意,在这种情况下,IsAssignableFrom会为自己返回true,您可以通过将&& x != typeof(Item)添加到Where子句来轻松省略。

答案 1 :(得分:0)

您可以使用以下

public static class Program {
    static void Main(string[] args) {
        var items = Assembly.GetExecutingAssembly().GetTypes()
                            .Where(x => !x.IsAbstract && x.GetBaseTypes().Contains(typeof(Item)));




    }

    public static IEnumerable<Type> GetBaseTypes(this Type type) {
        if (type.BaseType == null) return type.GetInterfaces();

        return Enumerable.Repeat(type.BaseType, 1)
                         .Concat(type.GetInterfaces())
                         .Concat(type.GetInterfaces().SelectMany<Type, Type>(GetBaseTypes))
                         .Concat(type.BaseType.GetBaseTypes());
    }
}

public class Item { }
public class ItemA : Item { }
public class ItemB : ItemA { }
public abstract class ItemC : Item { }

用于查找基本类型的扩展方法取自Given a C# Type, Get its Base Classes and Implemented Interfaces

这样做的原因是Type只有BaseType(),我们需要递归迭代这些,以确保我们获得链中其他类的类型。

该计划产生ItemAItemB