예제 #1
0
    private static TypeInheritance GetInheritanceTree(this Type type, int distance)
    {
        var list = new TypeInheritance(type, distance);
        // Gives us a map of Interface + All ancestor interfaces in the entire hierarchy up.
        var interfaces = type
            .GetInterfaces()
            .Select(i => new { Interface = i, Ancestors = i.GetInterfaces().Traverse(TraverseKind.BreadthFirst, n => n.GetInterfaces()) });

        if (type.IsClass)
        {
            if (type.BaseType != null)
                list.Inheritance.Add(GetInheritanceTree(type.BaseType, distance + 1));

            list.Inheritance.AddRange(type
                // Add all interfaces of the type, but
                .GetInterfaces()
                // See if the map gives us where the interface members are implemented
                .Select(i => new { Interface = i, Map = type.GetInterfaceMap(i) })
                // Either it is a marker interface, or all members are declared by the type.
                // (explicit interface implementation or otherwise we are the first class in the hierarchy to introduce the interface).
                .Where(i =>
                    // Detect marker interfaces separately, and add them always as long as they don't show up in others upward.
                    (!i.Map.TargetMethods.Any() && !interfaces.SelectMany(n => n.Ancestors).Any(t => t == i.Interface)) ||
                        // For interfaces with members, we can get the map and check if they are declared in the current type.
                        // Note that this brings into this type the interfaces that have a completely overriden implementation (our intended design).
                    (i.Map.TargetMethods.Any() && i.Map.TargetMethods.All(m => m.DeclaringType == type)))
                .Select(i => GetInheritanceTree(i.Interface, distance + 1)));
        }
        else
        {
            // Then we only add those interfaces that do not show up as ancestors in any other 
            // interface in the list.
            list.Inheritance.AddRange(interfaces
                .Select(i => i.Interface)
                .Where(i => !interfaces.SelectMany(n => n.Ancestors).Any(t => t == i))
                .Select(i => GetInheritanceTree(i, distance + 1)));
        }

        return list;
    }
예제 #2
0
	private static void PrintTypeList(TypeInheritance list, int indentLevel)
	{
		Console.WriteLine(
			Enumerable.Range(0, indentLevel).Aggregate("", (s, level) => s += '\t') +
			list.Type.Name + " (" + list.Distance + ")");

		indentLevel++;

		foreach (var inner in list.Inheritance)
		{
			PrintTypeList(inner, indentLevel);
		}
	}