Как определить, является ли T IEnumerable, а если так получится типа Т2? - PullRequest
5 голосов
/ 07 января 2011

Мне известно о этом вопросе, и о его последующих действиях, а также этом одном, но я не могу соединить их таким образом, который поможет мне сделатьчто я хочу сделать:

У меня есть универсальный тип, и я хочу проверить, что T является struct ИЛИ если он реализует IEnumerable<T2>, тогда я хотел бы проверить, что T2 является struct.

До сих пор я здесь ('scusppy код, это экспериментально):

private class TestClass<T>
{
    public TestClass()
    {
        Type type = typeof(T);
        //(detecting T == IEnumerable<something> ommitted for clarity)
        Type enumerableType = type.GetInterfaces()
                .Where(t => t.IsGenericType)
                .Select(t => t.GetGenericTypeDefinition())
                .Where(t => t == typeof(IEnumerable<>))
                .FirstOrDefault();
        if(enumerableType != null) 
        {
            Type enumeratedType = type.GetGenericArguments().First();
            if(!enumeratedType.IsValueType) //throw etc...
        }
    }
}

У меня проблема в том, что enumerableType это IEnumerable<>, поэтому enumeratedType выглядит как T, а не как я (например, new TestClass<int[]>()).

Ответы [ 3 ]

4 голосов
/ 07 января 2011

Ваша проблема в том, что вы выбрали тип, содержащий все данные, в пользу стертого шаблона универсального типа.

2 голосов
/ 07 января 2011

Из Блог Мэтта Уоррена :

internal static class TypeSystem {
    internal static Type GetElementType(Type seqType) {
        Type ienum = FindIEnumerable(seqType);
        if (ienum == null) return seqType;
        return ienum.GetGenericArguments()[0];
    }
    private static Type FindIEnumerable(Type seqType) {
        if (seqType == null || seqType == typeof(string))
            return null;
        if (seqType.IsArray)
            return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
        if (seqType.IsGenericType) {
            foreach (Type arg in seqType.GetGenericArguments()) {
                Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
                if (ienum.IsAssignableFrom(seqType)) {
                    return ienum;
                }
            }
        }
        Type[] ifaces = seqType.GetInterfaces();
        if (ifaces != null && ifaces.Length > 0) {
            foreach (Type iface in ifaces) {
                Type ienum = FindIEnumerable(iface);
                if (ienum != null) return ienum;
            }
        }
        if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
            return FindIEnumerable(seqType.BaseType);
        }
        return null;
    }
}
0 голосов
/ 07 января 2011

Я считаю, что этот код делает то, что вы хотите.
Возможно, вы захотите немного его почистить.

public class TestClass<T>
{
    public TestClass()
    {
        bool hasStruct = false;
        Type t1 = this.GetType().GetGenericArguments()[0];
        if(t1.IsValueType){
            hasStruct = true;
        }
        if (t1.IsGenericType)
        {
            Type t = t1.GetGenericArguments()[0];
            if (t.IsValueType)
            {
                hasStruct = true;
            }
        }

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...