如何判断Type是否实现了IList<>?

时间:2009-06-04 16:12:10

标签: .net generics reflection

我想编写一个使用Reflection来判断给定Type是否实现IList<T>的方法。例如:

IsGenericList(typeof(int))                       // should return false
IsGenericList(typeof(ArrayList))                 // should return false
IsGenericList(typeof(IList<int>))                // should return true
IsGenericList(typeof(List<int>))                 // should return true
IsGenericList(typeof(ObservableCollection<int>)) // should return true

在我的用法中,我可以假设类型将始终是实例化的泛型类型(或者根本不是通用的类型)。

不幸的是,这并不像它应该的那么容易。显而易见的解决方案:

public bool IsGenericList(Type type)
{
    return typeof(IList<>).IsAssignableFrom(type);
}

不起作用;它总是返回false。显然未实例化的通用类型(如IList<>)不会按照我期望的方式实现IsAssignable:IList<>无法从List<T>分配。

我也试过这个:

public bool IsGenericList(Type type)
{
    if (!type.IsGenericType)
        return false;
    var genericTypeDefinition = type.GetGenericTypeDefinition();
    return typeof(List<>).IsAssignableFrom(genericTypeDefinition);
}

即,将type转换为其未实例化的通用,例如IList<int> - &gt; IList<>,然后再次尝试IsAssignableFrom。当type是实例化的IList<T>时,例如IList<int>IList<object>等,这将返回true。但是对于实现IList<T>的类,例如List<int>,它返回false ,ObservableCollection<double>等,显然IList<>无法从List<>转让。再一次,不是我所期待的。

如何编写IsGenericList并使其工作如上例所示?

8 个答案:

答案 0 :(得分:26)

实际上,您不能拥有泛型类型定义的实例。因此,IsAssignableFrom()方法按预期工作。要实现您的目标,请执行以下操作:

public bool IsGenericList(Type type)
{
    if (type == null) {
        throw new ArgumentNullException("type");
    }
    foreach (Type @interface in type.GetInterfaces()) {
        if (@interface.IsGenericType) {
            if (@interface.GetGenericTypeDefinition() == typeof(ICollection<>)) {
                // if needed, you can also return the type used as generic argument
                return true;
            }
        }
    }
    return false;
}

出于好奇,你需要做什么?

答案 1 :(得分:14)

我也想测试一个类型是否为某些T实现了IList<T>。我对Lucero's answer进行了明显的更改,但它导致原始答案中没有subtle bug。这是我的最终编辑:

    /// <summary>
    /// Test if a type derives from IList of T, for any T.
    /// </summary>
    public bool TestIfGenericList(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }

        var interfaceTest = new Predicate<Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));

        return interfaceTest(type) || type.GetInterfaces().Any(i => interfaceTest(i));
    }

答案 2 :(得分:2)

Lucero / Reed Copsey现在都有正确的解决方案。只是为了使它更简洁,这里是LINQified形式:

var isGenericList = type.GetInterfaces().Any(t => t.IsGenericType && 
    t.GetGenericTypeDefinition() == typeof(IList<>));

答案 3 :(得分:2)

使用此: http://msdn.microsoft.com/en-us/library/system.type.findinterfaces.aspx

我试过了:

 public class Test : IList<string>
 {
//implementation left out...
 }

class Program
    {
        static void Main(string[] args)
        {
            Test t = new Test();
            TypeFilter myFilter = new TypeFilter(MyInterfaceFilter);

            Type type = t.GetType();
            Type[] x = type.FindInterfaces(myFilter, "System.Collections.Generic.IList");
            Console.WriteLine(x.Length);

        }

        public static bool MyInterfaceFilter(Type typeObj, Object criteriaObj)
        {
            if (typeObj.ToString().Contains(criteriaObj.ToString()))
                return true;
            else
                return false;
        }
    }

答案 4 :(得分:1)

这会通过你的考试......

public static bool IsGenericList( Type type )
{
  return type.Name == "IList`1" || type.GetInterface( "IList`1" ) != null;
}

答案 5 :(得分:0)

您是否尝试过调用Type.GetInterface()?从帮助中不完全清楚,但我认为除了类型本身之外,它还将搜索由基类型实现的接口。如果没有,您可以随时循环浏览Type.BaseType并再次致电GetInterface()

答案 6 :(得分:0)

我喜欢Colonel Panic's answer,但我决定使答案更为通用,以便在其他情况下重用它:

    public static bool InstanceOfGenericType(this Type self, Type genericType)
    {
        return self.IsGenericType && self.GetGenericTypeDefinition() == genericType;
    }

    public static bool InstanceOfGenericInterface(this Type self, Type ifaceType)
    {
        return self.InstanceOfGenericType(ifaceType) 
            || self.GetInterfaces().Any(i => i.InstanceOfGenericType(ifaceType));
    }

    public static bool IsIList(this Type t)
    {
        return t.InstanceOfGenericInterface(typeof(IList<>));
    }

答案 7 :(得分:-3)

使用“is”运算符:

  

is运算符用于检查   是否为对象的运行时类型   与给定类型兼容。