Get only direct interface instead of all?
As far as I can tell, none of the posted solutions work for typeof(C1)
and typeof(I3)
in the example below.
I think the correct answer is that it is not possible to get the directly implemented interfaces using out-of-the-box framework calls.
private interface I1 { }
private interface I2 : I1 { }
private interface I3 : I2, I1 { }
public class C1 : I3, I1 { }
This is a nice piece from a duplicate question:
public static class TypeExtensions {
public static IEnumerable<Type> GetInterfaces(this Type type, bool includeInherited)
{
if (includeInherited || type.BaseType == null)
return type.GetInterfaces();
else
return type.GetInterfaces().Except(type.BaseType.GetInterfaces());
}
}
And usage:
foreach(Type ifc in typeof(Some).GetInterfaces(false)) {
Console.WriteLine(ifc);
}
Firstly, the MSDN snippet you've posted doesn't have anything to do with your actual question. It deals with when you have, for example, a generic type such as class Foo<T> where T : IEnumerable
, and you try calling GetInterfaces
on the type-parameter T
, for example through typeof(Foo<>).GetGenericArguments().Single().GetInterfaces().
Secondly, the problem is slightly ill-specified. Note that when a class implements an interface, it must implement all of the interfaces 'inherited' by that interface. It's simply a C# convenience feature that lets you omit the inherited interfaces in the class-declaration. In your example, it's perfectly legal (and no different) to explicitly include the 'inherited' GHI
interface:
class ABC : DEF, GHI {...}
I've assumed that what you really want to do is find a 'minimal set' of interfaces that 'covers' all of the type's implemented interfaces. This results in a slightly simplified version of the Set cover problem.
Here's one way to solve it, without any attempt whatsoever to be algorithmically efficient. The idea is to produce the minimal interface-set by filtering out those interfaces that are already implemented by other interfaces implemented by the type.
Type type = ...
var allInterfaces = type.GetInterfaces();
var minimalInterfaces = from iType in allInterfaces
where !allInterfaces.Any(t => t.GetInterfaces()
.Contains(iType))
select iType;
( EDIT - Here's a better way of doing the above:
var minimalInterfaces = allInterfaces.Except
(allInterfaces.SelectMany(t => t.GetInterfaces()));
)
For example, for List<int>
:
allInterfaces:
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
System.Collections.IEnumerable
System.Collections.IList
System.Collections.ICollection
minimalInterfaces:
System.Collections.Generic.IList`1[System.Int32]
System.Collections.IList
Do note that this solution covers interface 'hierarchies' only (which is what you appear to want), not how they relate to the class's class hierarchy. In particular, it pays no attention to where in a class's hierarchy an interface was first implemented.
For example, let's say we have:
interface IFoo { }
interface IBar : IFoo { }
interface IBaz { }
class Base : IBar { }
class Derived : Base, IBaz { }
Now if you try using the solution I've described to get the minimal interface-set for Derived
, you would get IBaz
as well as IBar
. If you don't want IBar
, you would have to go to more effort: eliminate interfaces implemented by base-classes. The easiest way to do this would be to remove from the minimal interface-set those interfaces implemented by the class's immediate base-class, as is mentioned in @MikeEast's answer.