Como determinar se um tipo implementa um tipo específico de interface genérica

Suponha as seguintes definições de tipo:

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

Como faço para descobrir se o tipo Foo implementa a interface genérica IBar quando apenas o tipo desconfigurado está disponível?

Usando a resposta dos TcKs, isso também pode ser feito com a seguinte consulta LINQ:

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

Você precisa percorrer a tree de inheritance e localizar todas as interfaces para cada class na tree e comparar typeof(IBar<>) com o resultado da chamada Type.GetGenericTypeDefinition se a interface for genérica. É tudo um pouco doloroso, certamente.

Veja esta resposta e estas para mais informações e 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 uma extensão 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); } 

Exemplo de uso:

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

Você precisa verificar um tipo construído da interface genérica.

Você terá que fazer algo assim:

 foo is IBar 

porque IBar representa esse tipo construído. A razão pela qual você tem que fazer isso é porque se T é indefinido em sua checagem, o compilador não sabe se você quer dizer IBar ou IBar .

Estou usando uma versão um pouco mais simples do método de extensão @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(); 

Primeiro de tudo public class Foo : IFoo {} não compila porque você precisa especificar uma class em vez de T, mas assumindo que você faça algo como public class Foo : IFoo {}

então se você fizer

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

Para lidar com o sistema de tipos completamente, eu acho que você precisa lidar com recursion, por exemplo, IList : ICollection : IEnumerable , sem o qual você não sabe 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)); } 

Caso você quisesse um método de extensão que suportasse tipos de base genéricos, assim como interfaces, eu expandi a resposta do 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 se o tipo herda ou implementa um 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)); } 

Não deve haver nada de errado o seguinte:

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

Para crédito extra, você poderia pegar AmbiguousMatchException se quisesse fornecer um parâmetro de tipo genérico específico com sua consulta IBar.