Cómo determinar si un tipo implementa un tipo de interfaz genérico específico

Asum las siguientes definiciones de tipo:

public interface IFoo : IBar {} public class Foo : IFoo {} 

¿Cómo IBar si el tipo Foo implementa la interfaz genérica IBar cuando solo está disponible el tipo mutilado?

Al usar la respuesta de TcKs, también se puede hacer con la siguiente consulta LINQ:

 bool isBar = foo.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IBar<>)); 

Tienes que ir a través del árbol de herencia y encontrar todas las interfaces para cada clase en el árbol, y comparar typeof(IBar<>) con el resultado de llamar a Type.GetGenericTypeDefinition si la interfaz es genérica. Todo es un poco doloroso, sin duda.

Vea esta respuesta y estas para obtener más información y código.

 public interface IFoo : IBar {} public class Foo : IFoo {} var implementedInterfaces = typeof( Foo ).GetInterfaces(); foreach( var interfaceType in implementedInterfaces ) { if ( false == interfaceType.IsGeneric ) { continue; } var genericType = interfaceType.GetGenericTypeDefinition(); if ( genericType == typeof( IFoo<> ) ) { // do something ! break; } } 

Como una extensión de método auxiliar

 public static bool Implements(this Type type, I @interface) where I : class { if(((@interface as Type)==null) || !(@interface as Type).IsInterface) throw new ArgumentException("Only interfaces can be 'implemented'."); return (@interface as Type).IsAssignableFrom(type); } 

Ejemplo de uso:

 var testObject = new Dictionary(); result = testObject.GetType().Implements(typeof(IDictionary)); // true! 

Debe verificar contra un tipo construido de la interfaz genérica.

Tendrás que hacer algo como esto:

 foo is IBar 

porque IBar representa ese tipo construido. La razón por la que tiene que hacer esto es porque si T no está definido en su verificación, el comstackdor no sabe si se IBar o IBar .

Estoy usando una versión un poco más simple del método de extensión @GenericProgrammers:

 public static bool Implements(this Type type) where TInterface : class { var interfaceType = typeof(TInterface); if (!interfaceType.IsInterface) throw new InvalidOperationException("Only interfaces can be implemented."); return (interfaceType.IsAssignableFrom(type)); } 

Uso:

  if (!featureType.Implements()) throw new InvalidCastException(); 

En primer lugar, public class Foo : IFoo {} no comstack porque necesita especificar una clase en lugar de T, pero suponiendo que hace algo como public class Foo : IFoo {}

entonces si lo haces

 Foo f = new Foo(); IBar b = f as IBar; if(b != null) //derives from IBar<> Blabla(); 

Para abordar completamente el sistema de tipos, creo que debe manejar la recursión, por ejemplo, IList : ICollection : IEnumerable , sin la cual no sabría que IList finalmente implementa IEnumerable<> .

  /// Determines whether a type, like IList<int>, implements an open generic interface, like /// IEnumerable<>. Note that this only checks against *interfaces*. /// The type to check. /// The open generic type which it may impelement /// Whether the candidate type implements the open interface. public static bool ImplementsOpenGenericInterface(this Type candidateType, Type openGenericInterfaceType) { Contract.Requires(candidateType != null); Contract.Requires(openGenericInterfaceType != null); return candidateType.Equals(openGenericInterfaceType) || (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition().Equals(openGenericInterfaceType)) || candidateType.GetInterfaces().Any(i => i.IsGenericType && i.ImplementsOpenGenericInterface(openGenericInterfaceType)); } 

En caso de que desee un método de extensión que admita los tipos de bases generics, así como las interfaces, he ampliado la respuesta de sduplooy:

  public static bool InheritsFrom(this Type t1, Type t2) { if (null == t1 || null == t2) return false; if (null != t1.BaseType && t1.BaseType.IsGenericType && t1.BaseType.GetGenericTypeDefinition() == t2) { return true; } if (InheritsFrom(t1.BaseType, t2)) return true; return (t2.IsAssignableFrom(t1) && t1 != t2) || t1.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == t2); } 

Método para verificar si el tipo hereda o implementa un tipo genérico:

  public static bool IsTheGenericType(this Type candidateType, Type genericType) { return candidateType != null && genericType != null && (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition() == genericType || candidateType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == genericType) || candidateType.BaseType != null && candidateType.BaseType.IsTheGenericType(genericType)); } 

No debería haber nada malo en lo siguiente:

 bool implementsGeneric = (anObject.Implements("IBar`1") != null); 

Para obtener crédito adicional, puede capturar AmbiguousMatchException si desea proporcionar un parámetro de tipo genérico específico con su consulta IBar.