Как определить, является ли что-то IEnumerable <>? - PullRequest
3 голосов
/ 03 октября 2019

У меня есть Тип.

Как я могу определить, является ли это IEnumerable<>?

Эти:

typeof(IEnumerable<>).IsAssignableFrom(memberType);
typeof(IEnumerable<object>).IsAssignableFrom(memberType);

возвращают false для IEnumerable<int>

Принимая во внимание следующее:

typeof(IEnumerable).IsAssignableFrom(memberType);

возвращает true для строки.

Ответы [ 2 ]

4 голосов
/ 03 октября 2019

Отражение это весело;примечание: имейте в виду, что вы можете реализовать IEnumerable<X> и IEnumerable<Y> (и т. д.) для одного типа, поэтому для простоты здесь я просто сообщаю о первом найденном произвольно :

static void Main()
{
    Console.WriteLine(FindFirstIEnumerable(typeof(int))); // null
    Console.WriteLine(FindFirstIEnumerable(typeof(string))); // System.Char
    Console.WriteLine(FindFirstIEnumerable(typeof(Guid[]))); // System.Guid
    Console.WriteLine(FindFirstIEnumerable(typeof(IEnumerable<float>))); // System.Single
}

static Type FindFirstIEnumerable(Type type)
{
    if (type == null || !typeof(IEnumerable).IsAssignableFrom(type))
        return null; // anything IEnumerable<T> *must* be IEnumerable
    if (type.IsInterface && type.IsGenericType
        && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
    {
        return type.GetGenericArguments()[0];
    }
    foreach(var iType in type.GetInterfaces())
    {
        if (iType.IsGenericType &&
            iType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        {
            return iType.GetGenericArguments()[0];
        }
    }
    return null;
}

1 голос
/ 03 октября 2019

Ну ... я нашел способ сделать это ...

private static bool IsGenericEnumerable(this [NotNull] Type type) =>
            typeof(IEnumerable<>).IsAssignableFrom(type)
            || typeof(IEnumerable<object>).IsAssignableFrom(type)
            || (typeof(IEnumerable<char>).IsAssignableFrom(type) && type != typeof(string))
            || typeof(IEnumerable<byte>).IsAssignableFrom(type)
            || typeof(IEnumerable<sbyte>).IsAssignableFrom(type)
            || typeof(IEnumerable<ushort>).IsAssignableFrom(type)
            || typeof(IEnumerable<short>).IsAssignableFrom(type)
            || typeof(IEnumerable<uint>).IsAssignableFrom(type)
            || typeof(IEnumerable<int>).IsAssignableFrom(type)
            || typeof(IEnumerable<ulong>).IsAssignableFrom(type)
            || typeof(IEnumerable<long>).IsAssignableFrom(type)
            || typeof(IEnumerable<float>).IsAssignableFrom(type)
            || typeof(IEnumerable<double>).IsAssignableFrom(type)
            || typeof(IEnumerable<decimal>).IsAssignableFrom(type)
            || typeof(IEnumerable<DateTime>).IsAssignableFrom(type);

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

...