Подтвердить что ты не робот

Проверьте, реализует ли тип общий интерфейс, не рассматривая общие аргументы типа

У меня есть интерфейс

public interface MyInterface<TKey, TValue>
{
}

Реализации не имеют значения. Теперь я хочу проверить, является ли данный тип реализацией этого интерфейса. Этот метод не работает для

public class MyClass : MyInterface<int, string>
{
}

Но я не знаю, как сделать чек.

public void CheckIfTypeImplementsInterface(Type type)
{
    var result1 = typeof(MyInterface<,>).IsAssignableFrom(type); --> false
    var result2 = typeof(MyInterface<int,string>).IsAssignableFrom(type); --> true
}

Что мне нужно сделать для того, чтобы result1 был правдой?

4b9b3361

Ответ 1

Насколько я знаю, единственный способ сделать это - получить все интерфейсы и посмотреть, соответствует ли общее определение требуемому типу интерфейса.

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Select(i => i.GetGenericTypeDefinition())
    .Contains(typeof(MyInterface<,>));

EDIT: Как отмечает Джон в комментариях, вы также можете:

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Any(i => i.GetGenericTypeDefinition() == typeof(MyInterface<,>));

Ответ 2

Как правило, такое поведение требуется только в тех случаях, когда интерфейс содержит некоторую функциональность, которая не зависит от параметров типового типа. Если у вас есть контроль над интерфейсами, лучшим решением является унаследовать части, зависящие от типа, от не зависящей от типа части. Например, если существующих интерфейсов коллекции не существует, можно определить их как:

interface ICountable 
  { CollectionAttribute Attributes {get;} int Count {get;} }
interface ICollection<T> : IEnumerable<T> ICountable
  { ... and other stuff ... }

Если бы это было сделано с помощью ICollection, тогда код, ожидавший IEnumerable<Animal>, но получивший объект типа CatList, который просто реализует IList<Cat>, не будет иметь проблем с использованием элемента Count этого объект (обратите внимание, что List<Animal> реализует не-общий ICollection, но другие реализации IList<Animal> могут не быть).

Как бы то ни было, если вы застряли в задаче с кодом как-то найти Count метод ICollection<Cat>, когда вы ожидаете IEnumerable<Animal>, может быть полезно построить что-то вроде Dictionary<Type, Func<IEnumerable<Animal>, int>, так что, как только вы обнаружите, что CatList реализует ICollection<Cat>.Count, вы можете построить делегат для метода, который передаст его аргумент ICollection<Cat>, вызовет Count на нем и вернет его результат. Если у вас есть такой словарь, то если вам дано другое CatList, вы сможете просто вызвать делегата из словаря.