在 .NET 3.5 中使用反射生成子类列表

Posted

技术标签:

【中文标题】在 .NET 3.5 中使用反射生成子类列表【英文标题】:Generating a list of child classes with reflection in .NET 3.5 【发布时间】:2012-12-03 12:27:39 【问题描述】:

在运行时,我想指定一个父类,然后程序将生成所有子类的列表(无论多少代)。例如,如果我有 Entity 作为父级,Item:EntityActor:Entity,就会有两个字符串,“Actor”和“Item”。

我看到System.Reflection.TypeInfo 正是我正在寻找的。但是,这似乎是 .NET 4.5 独有的,不幸的是我的环境卡在 3.5。

在 .NET 3.5 中是否有其他方法可以做到这一点,还是我应该考虑升级?

【问题讨论】:

【参考方案1】:
var pType = typeof(Entity);
IEnumerable<string> children = Enumerable.Range(1, iterations)
   .SelectMany(i => Assembly.GetExecutingAssembly().GetTypes()
                    .Where(t => t.IsClass && t != pType
                            && pType.IsAssignableFrom(t))
                    .Select(t => t.Name));

Demo

【讨论】:

复制时要小心,不要把它倒过来,不要太注意。 t.IsAssignableFrom(pType) 将返回 false。【参考方案2】:

一种可能的方法是使用Type.IsAssignableFrom 方法。您将遍历所有类型,并选择那些为 true 的类型。

基本上是这样的

Type parent = Type.GetType("Entity");
Type[] types = Assembly.GetExecutingAssembly().GetTypes(); // Maybe select some other assembly here, depending on what you need
Type[] inheritingTypes = types.Where(t => parent.IsAssignableFrom(t));

我目前没有可用的编译器,所以我无法验证它,但它应该大部分是正确的

【讨论】:

哦,太好了,我首先要问生成列表的最佳方法,这或多或少是从快速搜索 SO 中推荐的方法。 我会指出Assembly.GetExecutingAssembly() 不能跨程序集边界工作。如果你想跨程序集工作,你可以使用AppDomain.CurrentDomain.GetAssemblies() @Danjen:请注意,这也会返回接口和父类本身。如果不需要,则需要进行一些过滤。此外,正如 Kendall 所指出的,您需要考虑一下要搜索的程序集/程序集。但这应该可以帮助您入门。【参考方案3】:

这是我用来在选定程序集中查找某个类(也可以是抽象类)的所有子类的方法:

public class InheritedFinder

    public static Type[] FindInheritedTypes(
        Type parentType, Assembly assembly)
    
        Type[] allTypes = assembly.GetTypes();
        ArrayList avTypesAL = new ArrayList();

        return allTypes.Where(
            t => parentType.IsAssignableFrom(t) && t != parentType).ToArray();
    

只需调用

var availableTypes = InheritedFinder.FindInheritedTypes(
        typeof(YourBaseClass),
        System.Reflection.Assembly.GetExecutingAssembly());

这将为您提供 YourBaseClass 的可用子级列表。这样做的好处是——它还可以找到孩子的孩子,所以你可以使用多层次的抽象类。如果您需要创建每个孩子的实例,很简单:

var availableTypes= InheritedFinder.FindInheritedTypes(
    typeof(Shape), System.Reflection.Assembly.GetExecutingAssembly());
foreach (var t in availableTypes)

    try
    
        YourBaseClass nInstance = (YourBaseClass)Activator.CreateInstance(t);
        //nInstance is now real instance of some children
    
    catch (Exception e)
    
        //recommended to keep here - it'll catch exception in case some class is abstract (=can't create its instance)
    

【讨论】:

【参考方案4】:

您可以使用以下代码:

var parrents = Assembly.GetExecutingAssembly().GetTypes().Where(a => typeof(Person).IsAssignableFrom(a)).ToList();

【讨论】:

以上是关于在 .NET 3.5 中使用反射生成子类列表的主要内容,如果未能解决你的问题,请参考以下文章

SWIG C++ to Python:生成 Python 列表的子类

如何在 ASP.NET 中动态生成列表项到无序列表?

通过反射构造泛型(混合类型列表示例)

C#从反射类型实例化通用列表[重复]

.NET 预定义调色板颜色列表的 MS 图表?

windows10上安装 .NET Framework 3.5