【问题标题】:Getting list of Inherited types doesn't work for all types获取继承类型列表不适用于所有类型
【发布时间】:2015-03-17 16:14:05
【问题描述】:

我写了一个小方法来列出继承的类型,但它不适用于TreeNode,例如:

假设这个类:

class B { }
class A : B { }
class C :TreeNode { }

然后:

GetInheritedTypes(typeof(A)); //typeof(B)
GetInheritedTypes(typeof(C)); // 0 items

列出它们的方法:

List<Type> GetInheritedTypes(Type baseType) 
{ 
    return Assembly.GetAssembly(baseType)
                   .GetTypes()
                   .Where(type => type != baseType && type.IsAssignableFrom(baseType))
                   .ToList(); 
} 

为什么 GetInheritedTypes(typeof(C)) 返回 0 个项目而不是 Typeof(TreeNode)

【问题讨论】:

  • CTreeNode 是否在同一个程序集中声明?
  • @MarcinJuraszek:不,他们不是,除非 Jack 正在努力将 C 类型添加到 System.Windows.Forms.DLL。
  • @EricLippert 好点。或者他有自己的TreeNode 类声明? :)
  • @EricLippert:哦,这实际上是在询问System.Windows.Forms.TreeNode(或者可能是关于System.Web.Ui.WebControls.TreeNode),还是一个名为TreeNode 的自定义类?
  • @Jamiec IsAssignableFrom 将为父母的父母返回 true。对于存在与继承层次结构无关的有效隐式转换(即实现的接口)的类型,它也将返回 true。

标签: c# reflection inherited


【解决方案1】:

为什么 GetInheritedTypes(typeof(C)) 返回 0 个项目而不是 Typeof(TreeNode)?

因为TreeNodeC 不在同一个程序集中。您的查询是“来自与 C 相同的程序集中的所有类型,给我 C 可分配给的那些”。

我怀疑你的实际问题是:

如何列出给定类型的所有基本类型?

对程序集中的所有类型进行搜索并检查哪些是可分配的。这就像通过问你所在城市的每个人“你是杰克的妈妈吗?”来弄清楚你妈妈是谁。而不是问杰克“你妈妈是谁?”。

这样的东西会好很多:

public static IEnumerable<Type> BaseTypes(this Type type)
{
    if (type == null) throw new ArgumentNullException("type");
    Type baseType = type;
    while(true)
    {
        baseType = baseType.BaseType;
        if (baseType == null) 
            break;
        yield return baseType;
    }
}

一位评论者问

如果你想获得所有实现的接口怎么办?

在类型对象上调用GetInterfaces()

(这篇文章的早期版本建议获取接口的传递闭包;我忘记了 GetInterfaces 已经这样做了。)

我原来的代码是怎么破的?

好吧,假设你有一个类型

class D<T> {}

还有一个班级

class E : D<int> {}

现在你问“给定E,列出程序集中的所有类型X,以便可以将E 类型的值分配给X 类型的变量”。好吧,D&lt;T&gt; 在程序集中; D&lt;T&gt;是这样的类型吗?不可以。E 可以分配给D&lt;int&gt; 类型的变量,而不是D&lt;T&gt; 类型的变量。

“可赋值”关系和“继承自”关系有相当多的重叠,但它们根本不是相同的关系,所以不要假装它们是。 p>

【讨论】:

  • 如果 type 实现了多个接口怎么办?
  • 很棒的例子。我假设您可以通过执行 relation = t =&gt; t.GetInterfaces().Concat(t.BaseType == null ? Enumerable.Empty&lt;Type&gt;() : new[] { t.BaseType }); 之类的操作来获取所有已实现的类型(不包括可分配的泛型类型、基本类型 + 接口),对吗?
  • @moarboilerplate:我删除了我很棒的示例,因为我意识到它是不必要的。 (我在考虑“所有接口”关系的 Roslyn 实现,而不是反射实现。)但是,是的,您可以按照您的建议获得“所有基本类型和接口的传递闭包”。
【解决方案2】:

您只是在与C 相同的程序集中枚举类,并且可能TreeNode 驻留在不同的程序集中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多