如何检查泛型类型定义是否继承另一个泛型类型定义

问题描述:

我想检查一个开放泛型类型定义是否实现了一些开放泛型接口。请看下面的例子:如何检查泛型类型定义是否继承另一个泛型类型定义

public interface IService<T> { } 

public class ServiceImpl<T> : IService<T> { } 

private static bool OpenGenericTypeImplementsOpenGenericInterface(
    Type derivedType, Type interfaceType) 
{ 
    return derivedType.GetInterfaces().Contains(interfaceType); 
} 

[TestMethod] 
public void Verify() 
{ 
    Type openGenericImplementation = typeof(ServiceImpl<>); 

    Type expectedInterfaceType = typeof(IService<>); 

    bool implDoesImplementInterface = OpenGenericTypeImplementsOpenGenericInterface(
     openGenericImplementation, expectedInterfaceType); 

    // This assert fails. Why? 
    Assert.IsTrue(implDoesImplementInterface); 
} 

我发现从Type.GetInterfaces()方法返回的类型不匹配typeof(IService<>)返回的类型。我想不通这是为什么,以及如何正确地验证一些通用的类型定义是否继承或实现一些其他的泛型类型定义。

这是怎么回事,我该如何解决解决这个问题?

+0

Inline:Assert.IsTrue(OpenGenericTypeImplements);什么是OpenGenericTypeImplements? – HABJAN 2011-01-06 19:36:25

+1

@HABJAN:你说得对。犯了一个错字。修复。 – Anne 2011-01-06 19:50:55

的问题是,GetInterfaces返回封闭类型的,所以你需要使用GetGenericTypeDefinition打开它们:

public static bool ImplementsOpenInterface(Type type, Type openInterfaceType) { 
    Contract.Requires(type != null); 
    Contract.Requires(openInterfaceType != null); 
    Contract.Requires(openInterfaceType.IsGenericTypeDefinition); 
    Type[] interfaces = type.GetInterfaces(); 
    if (interfaces == null) { 
     return false; 
    } 

    return interfaces 
     .Where(x => x.IsGenericType) 
     .Select(x => x.GetGenericTypeDefinition()) 
     .Any(x => x == openInterfaceType); 
} 
+1

很酷。这样可行。谢谢。 – Anne 2011-01-06 19:57:19

GetInterfaces()会返回一个封闭式的对象与它实现与接口的泛型参数。

相反,使用LINQ:

return derivedType.GetInterfaces().Any(i => 
    i == interfaceType 
|| (i.ContainsGenericParameters && i.GetGenericTypeDefinition() == interfaceType)) 

此代码检查任何它所实现的接口是否是你的接口的参数化版本。

这种变化你的方法,它会工作:

private static bool OpenGenericTypeImplementsOpenGenericInterface(
    Type derivedType, Type interfaceType) 
{ 
    return derivedType.GetInterface(interfaceType.Name) != null; 
} 

我有必要在此基础上扩展以包含除接口外的类型继承。以下是我想出了:

interface IFace<T> {} 
class Impl<T> : IFace<T> {} 
class Derived<T> : Impl<T> {} 

public static bool InheritsFrom(this Type tDerived, Type tBase) 
{ 
    if (tDerived.IsSubtypeOf(tBase)) return true; 
    var interfaces = tDerived.GetInterfaces() 
          .Select(i => i.IsGenericType ? i.GetGenericTypeDefinition() : i); 
    return interfaces.Contains(tBase); 
} 
public static bool IsSubtypeOf(this Type tDerived, Type tBase) 
{ 
    var currentType = tDerived.BaseType; 
    while (currentType != null) 
    { 
     if (currentType.IsGenericType) 
      currentType = currentType.GetGenericTypeDefinition(); 
     if (currentType == tBase) return true; 
     currentType = currentType.BaseType; 
    } 
    return false; 
} 

注意的是,虽然这些方法可以在任何两种类型的工作,他们认为,如果一个泛型类型通过,类型是开放的(也就是说,它是泛型类型定义没有定义的类型参数)。