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

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

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

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

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

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

4b9b3361

Ответ 1

// 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 - это общий интерфейс, о котором идет речь.

Ответ 2

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

Ответ 3

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

Ответ 4

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

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!

Ответ 5

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

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

Ответ 6

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

public class MyType : ISomeInterface
{
}

MyType o = new MyType();

if(o is ISomeInterface)
 {
 }

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

В этом случае здесь очень большой 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