Выяснение, реализует ли тип универсальный интерфейс - PullRequest
54 голосов
/ 14 июля 2009

Допустим, у меня есть тип, MyType. Я хочу сделать следующее:

  1. Узнайте, реализует ли MyType интерфейс IList для некоторого T.
  2. Если ответ на (1) положительный, выясните, что такое Т.

Кажется, что способ сделать это - GetInterface (), но он позволяет выполнять поиск только по определенному имени. Есть ли способ поиска «всех интерфейсов, которые имеют форму IList» (Если это возможно, было бы также полезно, если бы он работал, если интерфейс был подинтерфейсом IList.)

Связанный: Как определить, реализует ли тип определенный тип универсального интерфейса

Ответы [ 7 ]

83 голосов
/ 14 июля 2009
// this conditional is necessary if myType can be an interface,
// because an interface doesn't implement itself: for example,
// typeof (IList<int>).GetInterfaces () does not contain IList<int>!
if (myType.IsInterface && myType.IsGenericType && 
    myType.GetGenericTypeDefinition () == typeof (IList<>))
    return myType.GetGenericArguments ()[0] ;

foreach (var i in myType.GetInterfaces ())
    if (i.IsGenericType && i.GetGenericTypeDefinition () == typeof (IList<>))
        return i.GetGenericArguments ()[0] ;

Редактировать: Даже если myType реализует IDerivedFromList<>, но не напрямую IList<>, IList<> будет отображаться в массиве, возвращаемом GetInterfaces().

Обновление: добавлена ​​проверка для граничного случая, где myType - рассматриваемый общий интерфейс.

11 голосов
/ 14 июля 2009

Используя отражение (и немного LINQ), вы можете легко сделать это:

public static IEnumerable<Type> GetIListTypeParameters(Type type)
{
    // Query.
    return
        from interfaceType in type.GetInterfaces()
        where interfaceType.IsGenericType
        let baseInterface = interfaceType.GetGenericTypeDefinition()
        where baseInterface == typeof(IList<>)
        select interfaceType.GetGenericArguments().First();
}

Во-первых, вы получаете интерфейсы по типу и отфильтровываете только те, которые являются универсальным типом.

Затем вы получите определение общего типа для этих типов интерфейса и посмотрите, совпадает ли оно с IList<>.

Оттуда просто получить общие аргументы для исходного интерфейса.

Помните, что тип может иметь несколько реализаций IList<T>, поэтому возвращается IEnumerable<Type>.

4 голосов
/ 11 октября 2011
    public static bool Implements<I>(this Type type) where I : class
    {
         if (!typeof(I).IsInterface)
         {
             throw new ArgumentException("Only interfaces can be 'implemented'.");
         }

         return typeof(I).IsAssignableFrom(type);
    }
1 голос
/ 17 декабря 2014

Используя предложение Антона Тихого, вот небольшой метод расширения, позволяющий проверить, реализует ли какой-либо тип универсальный интерфейс с заданными параметрами универсального типа:

public static class ExtensionMethods
{
    /// <summary>
    /// Checks if a type has a generic interface. 
    /// For example 
    ///     mytype.HasGenericInterface(typeof(IList<>), typeof(int)) 
    /// will return TRUE if mytype implements IList<int>
    /// </summary>
    public static bool HasGenericInterface(this Type type, Type interf, Type typeparameter)
    {
        foreach (Type i in type.GetInterfaces())
            if (i.IsGenericType && i.GetGenericTypeDefinition() == interf)
                if (i.GetGenericArguments()[0] == typeparameter)
                    return true;

        return false;
    }
}
1 голос
/ 24 сентября 2009

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

public static bool Implements<I>(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<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!
0 голосов
/ 14 июля 2009
Type[] typeArray2 = c.GetInterfaces();
for (int num2 = 0; num2 < typeArray2.Length; num2++)
{
     if (this == typeArray2[num2])
     {
          return true;
     }
}

http://www.hanselman.com/blog/DoesATypeImplementAnInterface.aspx

0 голосов
/ 14 июля 2009

Если я правильно понимаю ваш вопрос, это то, что вы пытаетесь сделать. Если нет, пожалуйста, объясните дальше.

public class MyType : ISomeInterface
{
}

MyType o = new MyType();

if(o is ISomeInterface)
 {
 }

edit: если вы измените свой вопрос, пожалуйста, добавьте тот факт, что вы отредактировали ... потому что теперь мой ответ выглядит так, как будто он не принадлежит.

В этом случае, здесь очень большой LINQ

            var item = typeof(MyType).GetInterfaces()
                            .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>))
                            .Select(t => t.GetGenericArguments().First())
                            .FirstOrDefault();

if( item != null )
 //it has a type
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...