2011-01-06 16 views
1

オープンジェネリック型定義がオープンジェネリックインタフェースを実装しているかどうかを確認しようとしています。私はType.GetInterfaces()メソッドから返される型はtypeof(IService<>)から返された型と一致しないことが判明ジェネリック型定義が別のジェネリック型定義から継承するかどうかを確認する方法

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

:以下のサンプルを見てください。私はそれがなぜ、そして何かジェネリック型定義が他のジェネリック型定義を継承し実装するかどうかを正しく検証する方法を理解できません。

ここでは何が起こっていますか、どのように解決すればこの問題を解決できますか?

+0

In Line:Assert.IsTrue(OpenGenericTypeImplements); OpenGenericTypeImplementsとは何ですか? – HABJAN

+1

@ハブヤン:そうです。タイプミス。修正しました。 – Anne

答えて

3

問題は、あなたがGetGenericTypeDefinitionを使用して、それらを開く必要がありますので、GetInterfaces戻り型を閉じたということです。

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

+1

ResharperはGetInterfacesがnullを返さないと伝えます – Sam

1

GetInterfaces()は、インターフェイスを実装する汎用パラメータを持つ閉じたTypeオブジェクトを返します。

代わりに、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

'interfaceType.Name'は' IService'1'です。 – SLaks

+0

あなたは何を言っていますか? – HABJAN

+0

ちょうどあなたが期待するものではない名前です。あなたの答えは正しいです。 – SLaks

0

私はする必要がありましたこれを拡張して、インタフェースに加えて型継承を組み込みます。ここに私が思い付いたものです。これらの方法は、任意の2種類で動作しますが、彼らはジェネリック型が渡された場合、タイプは(つまり、それがジェネリック型定義開放されていることを前提としていること

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

注意定義された型パラメータなし)。

関連する問題