如何检测T是否为IEnumerable <t2>,如果是,则获取T2的类型?</t2>

时间:2011-01-07 13:40:11

标签: c# generics reflection

我知道this问题,这是后续问题,也是this问题,但我不能将它们放在一起,以帮助我做我想做的事情做:

我有一个泛型类型,我想检查T是struct OR如果它实现IEnumerable<T2>,那么我想检查T2是struct

到目前为止,我已经到了这里('请原谅代码,这是实验性的):

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

我遇到的问题是enumerableTypeIEnumerable<>,因此enumeratedType出现为T,而不是我传入的任何内容(例如new TestClass<int[]>() }})。

3 个答案:

答案 0 :(得分:4)

您的问题是您选择了包含所有数据的类型,而不是使用已删除的通用类型模板。

尝试:

    Type enumerableType = type.GetInterfaces()
            .Where(t => t.IsGenericType)
            .Where(t => t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
            .Select(t => t.GetGenericArguments()[0])
            .FirstOrDefault();

答案 1 :(得分:2)

来自Matt Warren's Blog

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

答案 2 :(得分:0)

我相信这段代码可以满足您的需求。 你可能想稍微清理一下。

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

    }
}