Как определить, реализует ли тип определенного типа общего типа

Предположим, что следующие определения типов:

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

Как узнать, реализует ли тип Foo общий интерфейс IBar когда доступен только искаженный тип?

Используя ответ из TcK, это также можно сделать со следующим запросом LINQ:

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

Вам нужно пройти через дерево наследования и найти все интерфейсы для каждого classа в дереве и сравнить typeof(IBar<>) с результатом вызова Type.GetGenericTypeDefinition если интерфейс является общим. Конечно, это немного больно.

См. Этот ответ, и для получения дополнительной информации и кода.

 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; } } 

В качестве вспомогательного метода расширения

 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); } 

Пример использования:

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

Вы должны проверить построенный тип общего интерфейса.

Вам нужно будет сделать что-то вроде этого:

 foo is IBar 

потому что IBar представляет построенный тип. Причина, по которой вы должны это сделать, состоит в том, что если T не определено в вашей проверке, компилятор не знает, имеете ли вы IBar или IBar .

Я использую немного более простую версию метода расширения @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)); } 

Применение:

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

Прежде всего, public class Foo : IFoo {} не компилируется, потому что вам нужно указать class вместо T, но предполагая, что вы делаете что-то вроде public class Foo : IFoo {}

тогда, если вы это сделаете

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

Чтобы полностью решить систему типов, я считаю, что вам нужно обрабатывать рекурсию, например IList : ICollection : IEnumerable , без которой вы не знали бы, что IList конечном итоге реализует 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)); } 

Если вам нужен метод расширения, который будет поддерживать общие базовые типы, а также интерфейсы, я расширил ответ 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); } 

Способ проверки того, наследует ли тип или реализует общий тип:

  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)); } 

Не должно быть ничего плохого:

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

Для дополнительного кредита вы можете поймать AmbiguousMatchException, если вы хотите указать конкретный общий тип-параметр с запросом IBar.

  • Любой способ вызвать частный метод?
  • Как запретить разработчикам использовать reflection для доступа к приватным методам и конструкторам в Java?
  • Как ограничить setAccessible только «законным» использованием?
  • Java ищет метод с конкретной аннотацией и элементом annotations
  • Как я могу динамически добавлять поле в class в C #
  • Поиск параметров типа через reflection в Scala 2.10?
  • Как я могу получить примитивное имя типа в C #?
  • ClassCastException при литье в один class
  • Как я могу получить все classы в пространстве имен?
  • Использование отражения в C # для получения свойств вложенного объекта
  • Получить строковое имя свойства, используя reflection
  • Давайте будем гением компьютера.