2009-02-02 123 views

回答

306

通過使用從TcKs回答它也可以用以下LINQ查詢完成:

bool isBar = foo.GetType().GetInterfaces().Any(x => 
    x.IsGenericType && 
    x.GetGenericTypeDefinition() == typeof(IBar<>)); 
+1

這是一個非常優雅的解決方案!我在SO上看到的其他人使用foreach循環或更長的LINQ查詢。請記住,要使用這個,你需要有.NET框架3.5。 – 2009-11-10 03:25:14

+7

我建議你讓這個擴展方法成爲一個la http://bit.ly/ccza8B - 會很好地清理它! – 2010-07-27 23:06:01

4

你必須檢查構造類型的通用接口。

你將不得不做這樣的事情:

foo is IBar<String> 

因爲IBar<String>表示構造類型。您必須這樣做的原因是因爲如果您的支票中未定義T,編譯器不知道您的意思是IBar<Int32>還是IBar<SomethingElse>

31

你必須通過繼承樹上去,找到樹中的每個類的所有接口,並與調用Type.GetGenericTypeDefinition如果的接口是通用的結果比較typeof(IBar<>)。當然,這有點痛苦。

有關更多信息和代碼,請參閱this answerthese ones

+0

爲什麼不只是投到IBar 並檢查爲空? (我的意思是當然是用'as'投射) – 2009-02-02 14:04:58

+3

T是未知的,不能轉換成特定類型。 – sduplooy 2009-02-02 14:06:55

+0

@sduplooy:也許我錯過了T怎麼可能是未知的?它會編譯公共類Foo:IFoo {} – 2009-02-02 14:07:59

19
public interface IFoo<T> : IBar<T> {} 
public class Foo : IFoo<Foo> {} 

var implementedInterfaces = typeof(Foo).GetInterfaces(); 
foreach(var interfaceType in implementedInterfaces) { 
    if (false == interfaceType.IsGeneric) { continue; } 
    var genericType = interfaceType.GetGenericTypeDefinition(); 
    if (genericType == typeof(IFoo<>)) { 
     // do something ! 
     break; 
    } 
} 
+1

由於typeof(Foo)返回System.Type對象(描述Foo),GetType()調用將始終返回System.Type的類型。您應該更改爲typeof(Foo).GetInterfaces() – 2009-02-02 15:39:51

3

所有public class Foo : IFoo<T> {}首先不能編譯,因爲你需要指定一個類,而不是T,但假設你做這樣的事情public class Foo : IFoo<SomeClass> {}

那麼如果你

Foo f = new Foo(); 
IBar<SomeClass> b = f as IBar<SomeClass>; 

if(b != null) //derives from IBar<> 
    Blabla(); 
9

作爲一種輔助方法,擴展

public static bool Implements<I>(this Type type, I @interface) where I : class 
{ 
    if(((@interface as Type)==null) || !(@interface as Type).IsInterface) 
     throw new ArgumentException("Only interfaces can be 'implemented'."); 

    return (@interface as Type).IsAssignableFrom(type); 
} 

用法示例:

var testObject = new Dictionary<int, object>(); 
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true! 
4

我使用@GenericProgrammers擴展方法的稍微簡單一些的版本:

public static bool Implements<TInterface>(this Type type) where TInterface : class { 
    var interfaceType = typeof(TInterface); 

    if (!interfaceType.IsInterface) 
     throw new InvalidOperationException("Only interfaces can be implemented."); 

    return (interfaceType.IsAssignableFrom(type)); 
} 

用法:

if (!featureType.Implements<IFeature>()) 
     throw new InvalidCastException(); 
0

不應該有什麼錯了以下內容:

對於額外的信用,你可以趕上AmbiguousMatchException如果你想提供一個特定的通用型參數與伊巴爾查詢。

3

爲了完全處理類型系統,我認爲你需要處理遞歸,例如, IList<T>ICollection<T>IEnumerable<T>,沒有它你不會知道IList<int>最終實現了IEnumerable<>

/// <summary>Determines whether a type, like IList&lt;int&gt;, implements an open generic interface, like 
    /// IEnumerable&lt;&gt;. Note that this only checks against *interfaces*.</summary> 
    /// <param name="candidateType">The type to check.</param> 
    /// <param name="openGenericInterfaceType">The open generic type which it may impelement</param> 
    /// <returns>Whether the candidate type implements the open interface.</returns> 
    public static bool ImplementsOpenGenericInterface(this Type candidateType, Type openGenericInterfaceType) 
    { 
     Contract.Requires(candidateType != null); 
     Contract.Requires(openGenericInterfaceType != null); 

     return 
      candidateType.Equals(openGenericInterfaceType) || 
      (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition().Equals(openGenericInterfaceType)) || 
      candidateType.GetInterfaces().Any(i => i.IsGenericType && i.ImplementsOpenGenericInterface(openGenericInterfaceType)); 

    } 
1

在你想要將支持通用的基本類型以及接口擴展方法的情況下,我已經擴大sduplooy的回答是:

public static bool InheritsFrom(this Type t1, Type t2) 
    { 
     if (null == t1 || null == t2) 
      return false; 

     if (null != t1.BaseType && 
      t1.BaseType.IsGenericType && 
      t1.BaseType.GetGenericTypeDefinition() == t2) 
     { 
      return true; 
     } 

     if (InheritsFrom(t1.BaseType, t2)) 
      return true; 

     return 
      (t2.IsAssignableFrom(t1) && t1 != t2) 
      || 
      t1.GetInterfaces().Any(x => 
       x.IsGenericType && 
       x.GetGenericTypeDefinition() == t2); 
    } 
1

方法來檢查,如果該類型繼承或實現一個通用類型:

public static bool IsTheGenericType(this Type candidateType, Type genericType) 
    { 
     return 
      candidateType != null && genericType != null && 
      (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition() == genericType || 
      candidateType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == genericType) || 
      candidateType.BaseType != null && candidateType.BaseType.IsTheGenericType(genericType)); 
    } 
相關問題