簡體   English   中英

如何檢查泛型類型定義是否從另一個泛型類型定義繼承

[英]How to check if a generic type definition inherits from another generic type definition

我正在嘗試檢查開放通用類型定義是否實現了一些開放通用接口。 查看以下示例:

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<>)返回的類型不匹配。 我不知道為什么會這樣,以及如何正確驗證某個泛型類型定義是繼承還是實現了其他泛型類型定義。

這是怎么回事,如何解決此問題?

問題是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);
}

GetInterfaces()將返回一個封閉的Type對象,該對象帶有實現接口的通用參數。

而是使用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;
}

請注意,盡管這些方法適用於任何兩種類型,但它們都假定如果傳遞了泛型類型,則該類型是開放的(即,這是沒有定義的類型參數的泛型類型定義)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM