Проверьте, реализует ли тип общий интерфейс, не рассматривая общие аргументы типа
У меня есть интерфейс
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 был правдой?
Ответы
Ответ 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
, вы сможете просто вызвать делегата из словаря.