2011-01-06 109 views
1

我想檢查一個開放泛型類型定義是否實現了一些開放泛型接口。請看下面的例子:如何檢查泛型類型定義是否繼承另一個泛型類型定義

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

回答

3

的問題是,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

1

GetInterfaces()會返回一個封閉式的對象與它實現與接口的泛型參數。

相反,使用LINQ:

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

此代碼檢查任何它所實現的接口是否是你的接口的參數化版本。

1

這種變化你的方法,它會工作:

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

我有必要在此基礎上擴展以包含除接口外的類型繼承。以下是我想出了:

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

注意的是,雖然這些方法可以在任何兩種類型的工作,他們認爲,如果一個泛型類型通過,類型是開放的(也就是說,它是泛型類型定義沒有定義的類型參數)。