2009-07-13 8 views
51

私のタイプがMyTypeであるとします。タイプが汎用インターフェースを実装しているかどうかを調べる

  1. がMyTypeがIListインターフェイスを実装している場合(1)への答えはイエス、Tが何であるかを見つける場合には、いくつかのT.
  2. ため、見つける:私は、次の操作を実行します。

これはGetInterface()ですが、特定の名前で検索することしかできません。 「フォームのIListのあるすべてのインターフェイス」を検索する方法がある

関連(インターフェイスがIListののサブインターフェイスだった場合、それは働いていた場合、それはまた便利woudl可能な場合には。):How to determine if a type implements a specific generic interface type

答えて

80
// this conditional is necessary if myType can be an interface, 
// because an interface doesn't implement itself: for example, 
// typeof (IList<int>).GetInterfaces() does not contain IList<int>! 
if (myType.IsInterface && myType.IsGenericType && 
    myType.GetGenericTypeDefinition() == typeof (IList<>)) 
    return myType.GetGenericArguments()[0] ; 

foreach (var i in myType.GetInterfaces()) 
    if (i.IsGenericType && i.GetGenericTypeDefinition() == typeof (IList<>)) 
     return i.GetGenericArguments()[0] ; 

編集:myTypeIDerivedFromList<>ではなく、直接IList<>IList<>意志を実装した場合でもGetInterfaces()によって返された配列に現れます。

更新:は、myTypeが問題のジェネリックインターフェイスである場合のエッジケースのチェックを追加しました。反射(およびいくつかのLINQ)を使用して

+0

これは配列の大文字と小文字も扱います。配列を明示的にテストする場合は、 "if(myType.IsArray)return myType.GetElementType();"を使用します。 (そして、これは速いかもしれませんが、これはパフォーマンス上決定的ではないと思っています) – yoyo

+0

.IsInterfaceが必要な理由について興味があった私にとっては、GetGenericTypeDefinition()は非ジェネリック型で呼び出された場合にスローされます。 – GameFreak

+0

Type.IsGenericTypeプロパティは、netstandard 1.6以下では使用できません(したがって、.NET Core 1.0では使用できません)が、type.GetTypeInfo()。IsGenericTypeの代わりにTypeInfo.IsGenericTypeを使用できます。 – dotarj

0

の場合私はあなたの質問を正しく理解しています、これはあなたがやろうとしていることです。そうでない場合は、さらに説明してください。

public class MyType : ISomeInterface 
{ 
} 

MyType o = new MyType(); 

if(o is ISomeInterface) 
{ 
} 

編集:あなたの質問を変更場合、あなたはそれが属していないように私の答えは見える今edited..becauseという事実を追加してください。

その場合は、ここでは非常に大きなLINQがある

  var item = typeof(MyType).GetInterfaces() 
          .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>)) 
          .Select(t => t.GetGenericArguments().First()) 
          .FirstOrDefault(); 

if(item != null) 
//it has a type 
11

あなたは簡単にこれを行うことができます:

public static IEnumerable<Type> GetIListTypeParameters(Type type) 
{ 
    // Query. 
    return 
     from interfaceType in type.GetInterfaces() 
     where interfaceType.IsGenericType 
     let baseInterface = interfaceType.GetGenericTypeDefinition() 
     where baseInterface == typeof(IList<>) 
     select interfaceType.GetGenericArguments().First(); 
} 

まず、あなたはタイプのインターフェイスを取得し、唯一の一般的なタイプのあるもののためにフィルタリングされています。

次に、これらのインターフェイスタイプの汎用タイプ定義を取得し、それがIList<>と同じかどうかを確認します。

そこから、元のインターフェイスの汎用引数を取得するのは簡単です。

タイプにはIList<T>の実装が複数ある可能性があります。そのため、IEnumerable<Type>が返されます。ヘルパーメソッドの拡張機能として

+0

リターン式をカッコで囲み、最後に ".First()"を追加すると、長さ1のIEnumerable の代わりにTypeが返されます。 (個人的には、これはLINQであまりにも巧妙である例だと思いますが、それは私だけかもしれません) – yoyo

+0

@yoyoまたは、このメソッドの結果に対して 'First'を呼び出すことができます。このメソッドから 'First'を返すと、*間違った*型パラメータを*仮定しています。 – casperOne

+0

良い点@casperOne、OPのMyTypeはIList とIList を実装できます。ですから、質問は「Tを見つけてください」ではなく、「Tを見つける」ことであったはずです。受け入れられた答えはこれにも対処しません。 – yoyo

1

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

使用例:アントンTykhyyの提案を使用して

var testObject = new Dictionary<int, object>(); 
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true! 
4
public static bool Implements<I>(this Type type) where I : class 
    { 
     if (!typeof(I).IsInterface) 
     { 
      throw new ArgumentException("Only interfaces can be 'implemented'."); 
     } 

     return typeof(I).IsAssignableFrom(type); 
    } 
1

が、ここでいくつかのタイプを持つジェネリックインターフェイスを実装しているかどうかを確認するための小さな拡張メソッドであります1つのジェネリック型パラメータを指定します:

public static class ExtensionMethods 
{ 
    /// <summary> 
    /// Checks if a type has a generic interface. 
    /// For example 
    ///  mytype.HasGenericInterface(typeof(IList<>), typeof(int)) 
    /// will return TRUE if mytype implements IList<int> 
    /// </summary> 
    public static bool HasGenericInterface(this Type type, Type interf, Type typeparameter) 
    { 
     foreach (Type i in type.GetInterfaces()) 
      if (i.IsGenericType && i.GetGenericTypeDefinition() == interf) 
       if (i.GetGenericArguments()[0] == typeparameter) 
        return true; 

     return false; 
    } 
} 
関連する問題