Узнать, если тип реализует обобщенный интерфейс


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

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

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

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

7   51   2009-07-14 00:26:25

7 ответов:

// 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] ;

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

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

используя отражение (и некоторые 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> возвращается.

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

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

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!

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

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

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

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