在 .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:Entity
和 Actor: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 中使用反射生成子类列表的主要内容,如果未能解决你的问题,请参考以下文章