在 C# 中,如何获得 class 到基 class 的继承距离?

In C#, how could I get a class's inheritance distance to base class?

例如: 我有以下 classes:

public class A {}
public class B:A {}
public class C:B {}
public class D:C {}

如果有一个方便的方法,比如获取到基的层级距离class(而不是测试D.IsSubclassOf(B))来确定D更接近A,还是B更接近离A更近?

也许这对您有帮助:

public static int? GetDegreeOfRelationship(Type typeA, Type typeB)
{
    if (typeA.IsInterface || typeB.IsInterface) return null; // interfaces are not part of the inheritance tree
    if (typeA == typeB) return 0;

    int distance = 0;
    Type child;
    if (typeA.IsAssignableFrom(typeB))
    {
        child = typeB;
        while ((child = child.BaseType) != typeA)
            distance--;
        return --distance;
    }
    else if(typeB.IsAssignableFrom(typeA))
    {
        child = typeA;
        while ((child = child.BaseType) != typeB)
            distance++;
        return ++distance;
    }
    else
       return null;
}

用法:

int? distance = GetDegreeOfRelationship(typeof(A), typeof(D));      // -3
int? distance = GetDegreeOfRelationship(typeof(D), typeof(A));      //  3
int? distance = GetDegreeOfRelationship(typeof(B), typeof(B));      //  0
int? distance = GetDegreeOfRelationship(typeof(D), typeof(string)); // null

我已经截取了@kha 建议的代码并根据这个答案为您进行了改编:Get inheritance tree of type

public static class TypeExtensions
{
    public static IEnumerable<Type> GetInheritancHierarchy
        (this Type type)
    {
        for (var current = type; current != null; current = current.BaseType)
            yield return current;
    }
    public static int GetInheritanceDistance<TOther>(this Type type)
    {
        return type.GetInheritancHierarchy().TakeWhile(t => t != typeof(TOther)).Count();
    }
}

用法

var c = new C(); // 2
Console.WriteLine(c.GetType().GetInheritanceDistance<A>());

var b = new B(); // 1
Console.WriteLine(b.GetType().GetInheritanceDistance<A>());

您可以使用扩展方法来扩展 Type 的行为以遍历层次结构以得出到基地的距离或到基地的路径:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        System.Windows.Forms.Form a = new System.Windows.Forms.Form();
        Console.WriteLine(a.GetType().DistanceToBase());
        Console.WriteLine(a.GetType().PathToBase());
    }
}

public static class Extensions
{
    public static int DistanceToBase(this Type ob)
    {
        if (ob.BaseType == null)
        {
            return 0;
        }
        else return 1 + ob.BaseType.DistanceToBase();
    }

    public static string PathToBase(this Type ob)
    {
        if (ob.BaseType == null)
        {
            return ob.Name;
        }
        return ob.Name + "->" + ob.BaseType.PathToBase();
    }
}