2008年09月11日

インターフェースを実装しているかを調べる

   このエントリーをはてなブックマークに追加 Clip to Evernote
今度は、ICollectionを実装しているかを調べるコードをC#で書いてみた。
type.GetInterfaceMap(typeof(System.Collections.ICollection));

として例外が出なければOK。

もう一つの方法は、
GetInterface("System.Collections.ICollection");
で、null 以外が返ればOK.

じゃあ、IEnumerable<> を実装しているかを調べるには?
IEnumerable<int> でもIEnumerable<string>でも、なんでもOKにしたい。

 type.GetInterfaceMap(typeof(IEnumerable<>));
とやったけど、ダメだった。
指定したインターフェースが見つからないと、実行時例外が発生してしまう。
こうすれば、できるようだ。

 bool IsGenericsIEnumerable(Type type) {
     foreach (var t in type.GetInterfaces()) {
        if (t.IsGenericType && 
            t.GetGenericTypeDefinition() == typeof(IEnumerable<>) )
            return true;
     }
     return false;
 }

LINQを使えば、
 bool IsGenericsIEnumerable(Type type) {
     return type
         .GetInterfaces()
         .Any(t => t.IsGenericType && 
             t.GetGenericTypeDefinition() == typeof(IEnumerable<>));
 }


と書ける。


この記事へのコメント
最近ほぼ同じ事でハマったんですが、こんな方法はどうでしょう?

Type.GetType("System.Collections.Generic.IEnumerable`1");

これで認識しないもの(ユーザ定義のクラスなど)は

Type.GetType("FooBar.Baz`2, FooBar"); // FooBar.dllに定義されているFooBar名前空間のBaz<TA,TB>クラス

でいけると思います。
Posted by け〜くん at 2008年12月31日 07:48
け〜くんさん
こんな年の瀬にコメントありがとうございます。
僕もこのコードは考えたのですが、文字列というのが僕の趣味に合わなかったので、上記コードにした次第です。
ただ、1行で書けるという利点も捨てがたいものがありますね。


Posted by gushwell at 2008年12月31日 17:55
is 演算子はいかがですか?
Posted by x at 2009年05月26日 13:38
・ICollection<object> c = (ICollection<CustomClass> のインスタンス) がコンパイルエラー
・SuperClass s = (条件) ? SubClassA : SubClassB がコンパイルエラー
C# って。。。?
Posted by jam at 2009年05月26日 13:40
> is 演算子はいかがですか?
はい、is演算子でできればいいのですが、
やりたかったのは、Type型のオブジェクトから調べたかったのです。


Posted by Gushwell at 2009年05月26日 20:54
> ・ICollection<object> c = (ICollection<CustomClass> のインスタンス) がコンパイルエラー

ICollection c = new List<MySubClass>();

のようにするとか。
でも、そうしたい理由が思い浮かびません。ジェネリックの利点が失われてしまうように思います。

MySuperClass s = (条件) ? new MySubClass() : new MySuperClass();

はエラーにはなりませんが?
Posted by Gushwell at 2009年05月26日 20:55
 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/51624659