Вопрос по c#, reflection, .net – Выяснение, реализует ли тип универсальный интерфейс

54

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

Find out if MyType implements the IList interface, for some T. If the answer to (1) is yes, find out what T is.

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

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

Ваш Ответ

7   ответов
4
    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);
    }
0
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

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

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
83
// 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().

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

Для таких, как я, которым было любопытно, зачем нужен .IsInterface: GetGenericTypeDefinition () выдает, если он вызывается для неуниверсального типа.
Это касается и массивов, что приятно. Если вы хотите явно проверить массивы, используйте & quot; if (myType.IsArray), верните myType.GetElementType (); & quot; (И хотя это может быть быстрее, я надеюсь, что все это не критично для производительности!)
Потому что вы не можете реализовать открытый универсальный интерфейс.Dictionary<,> инвентарьIDictionary<`0, `1> где'0 а также'1 обратитесь к параметрам типаDictionary<,> - посмотрите в ILDasm или аналогичном.
Свойство Type.IsGenericType недоступно в netstandard 1.6 и ниже (и, следовательно, недоступно в .NET Core 1.0), но вместо этого вы можете использовать TypeInfo.IsGenericType: type.GetTypeInfo (). IsGenericType.
Что если MyType является открытым генетическим типом? Вам все еще нужно вызвать GetGenericTypeDefinitiin? Другими словами, почему typeof (Dictionary & lt;, & gt;). GetInterfaces (). Contains (typeof (IDictionary & lt;, & gt;)) возвращает false?
1

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!
1

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

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

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> возвращается

Если вы заключите возвращаемое выражение в скобки и добавите еще один & quot; .First () & quot; в конце он возвращает тип вместо IE1umerable & lt; Type & gt; длины-1, с которым немного легче иметь дело. (Лично я думаю, что это пример того, как быть слишком умным с LINQ, но, возможно, это только я.)
Хороший вопрос @casperOne, MyType OP может реализовать IList & lt; Foo & gt; и IList & lt; Bar & gt ;. Таким образом, вопрос должен был быть "найти T". не "найти Т". Принятый ответ также не касается этого.
@yoyo Или, вы можете просто позвонитьFirst по результатам этого метода. Если вы вернетесьFirst из этого метода выassuming один тип параметра, который является прямымwrong.

Похожие вопросы