【问题标题】:Generating a list of child classes with reflection in .NET 3.5在 .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 中是否有其他方法可以做到这一点,还是我应该考虑升级?

【问题讨论】:

    标签: c# reflection .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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多