我想编写一个使用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并使其工作如上例所示?
答案 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运算符用于检查 是否为对象的运行时类型 与给定类型兼容。