web-dev-qa-db-ja.com

型がC#リフレクションのあるインターフェースを実装しているかどうかを判断する方法

C#リフレクションは、あるSystem.Type型が何らかのインターフェースをモデル化しているかどうかを判断する方法を提供しますか?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);
499
Yippie-Ki-Yay

あなたは私の頭の上からいくつかの選択肢があります

  1. typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

  2. typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

一般的なインターフェースでは、少し違います。

typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))
847
Jeff

Type.IsAssignableFrom を使います。

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
59
Snea
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());

または

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
28
ajma
    public static bool ImplementsInterface( this Type type, Type ifaceType ) {
        Type[] intf = type.GetInterfaces();
        for ( int i = 0; i < intf.Length; i++ ) {
            if ( intf[ i ] == ifaceType ) {
                return true;
            }
        }
        return false;
    }

これは正しいリリースだと思います。3つの理由があります。

1)IsAssignableFromではなくGetInterfacesを使用します。IsAssignableFromは最終的にいくつかのチェックの後にGetInterfacesを呼び出します。
2)ローカル配列を反復処理するので、境界チェックは行われません。
3)Typeに対して定義されている==演算子を使用しているので、おそらくEqualsメソッドより安全です(Contains呼び出しで使用されます)。

12
Panos Theof

今やりました:

public static bool Implements<I>(this Type source) where I : class
{
  return typeof(I).IsAssignableFrom(source);
}

where I : interfaceを言ったかもしれませんが、interfaceは一般的なパラメータ制約オプションではありません。 classはできる限り近づいています。

使用法:

if(MyType.Implements<IInitializable>())
  MyCollection.Initialize();

私はImplementsと言ったのですが、それはより直感的です。私はいつもIsAssignableFromをフリップフロップします。

8
toddmo

他の誰かがすでに述べたように:ベンジャミン13年4月10日22時21分 "

注意を払わずにIsAssignableFromの引数を逆方向に取得するのは簡単でした。私は今GetInterfacesに行きます:p -

まあ、別の方法は、ある程度「ある程度普通の」考え方を満たす短い拡張方法を作成することです(そしてこれは自分の好みに基づいてそれを少し「より自然な」ものにするためのごく個人的な選択です):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }
}

それではもう少し一般的にはしないでください(それが本当におもしろいかどうかはよくわからないので、「シンタックス」糖のピンチをもう1つ渡しているだけなのでしょう)。

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }

    public static bool IsAssignableTo<TAssignable>(this Type type)
    {
        return IsAssignableTo(type, typeof(TAssignable));
    }
}

そのほうがずっと自然なことだと思いますが、ここでもまた非常に個人的な意見の問題です。

var isTrue = michelleType.IsAssignableTo<IMaBelle>();
7
Ehouarn Perret

最適なパフォーマンスを得るためのJeffの回答の修正(Pierre Arnaudによるパフォーマンステストのおかげで)

var type = typeof(MyType);
var implementsInterface = typeof(IMyInterface).IsAssignableFrom(type) && type.IsClass;

与えられたAssemblyの中でインターフェースを実装するすべての型を見つけるためには:

var implementations = typeof(TypeInTargetAssembly).Assembly.GetTypes()
                          .Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass);
7
Ben Wilde

IsAssignableFromTypeInfoに移動しました:

typeof(ISMSRequest).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo());
2
codeputer

正しい答えは

typeof(MyType).GetInterface(nameof(IMyInterface)) != null;

しかしながら、

typeof(MyType).IsAssignableFrom(typeof(IMyInterface));

次のコードがstringとIConvertibleで示されているように、間違った結果を返す可能性があります。

    static void TestIConvertible()
    {
        string test = "test";
        Type stringType = typeof(string); // or test.GetType();

        bool isConvertibleDirect = test is IConvertible;
        bool isConvertibleTypeAssignable = stringType.IsAssignableFrom(typeof(IConvertible));
        bool isConvertibleHasInterface = stringType.GetInterface(nameof(IConvertible)) != null;

        Console.WriteLine($"isConvertibleDirect: {isConvertibleDirect}");
        Console.WriteLine($"isConvertibleTypeAssignable: {isConvertibleTypeAssignable}");
        Console.WriteLine($"isConvertibleHasInterface: {isConvertibleHasInterface}");
    }

結果:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True
1
EricBDev

どうですか?

typeof(IWhatever).GetTypeInfo().IsInterface
0
LaWi

一般的なインターフェースIMyInterface<T>がある場合、これは常にfalseを返します。

  typeof(IMyInterface<>).IsAssignableFrom(typeof(MyType)) /* ALWAYS FALSE */

これもうまくいきません。

  typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface<>))  /* ALWAYS FALSE */

しかし、MyTypeIMyInterface<MyType>を実装している場合、これは機能し、trueを返します。

  typeof(IMyInterface<MyType>).IsAssignableFrom(typeof(MyType))

ただし、実行時に型パラメータTがわからなくなる可能性があります。やや巧妙な解決策は:

  typeof(MyType).GetInterfaces()
                .Any(x=>x.Name == typeof(IMyInterface<>).Name)

Jeffの解決策は少し厄介です。

  typeof(MyType).GetInterfaces()
         .Any(i => i.IsGenericType 
             && i.GetGenericTypeDefinition() == typeof(IMyInterface<>));

これはどんな場合にも使えるTypeの拡張メソッドです:

public static class TypeExtensions
{
    public static bool IsImplementing(this Type type, Type someInterface)
    {
        return type.GetInterfaces()
             .Any(i => i == someInterface 
                 || i.IsGenericType 
                    && i.GetGenericTypeDefinition() == someInterface);
    }
}

(上記はlinqを使っていることに注意してください。これはおそらくループより遅いです。)

あなたはその後することができます:

   typeof(MyType).IsImplementing(IMyInterface<>)
0
Diego

タイプまたはインスタンスがある場合、それらが特定のインターフェースをサポートしているかどうかを簡単に確認できます。

オブジェクトが特定のインターフェイスを実装しているかどうかをテストするには:

if(myObject is IMyInterface) {
  // object myObject implements IMyInterface
}

型が特定のインターフェイスを実装しているかどうかをテストするには:

if(typeof(IMyInterface).IsAssignableFrom(typeof(MyType))) {
  // type MyType implements IMyInterface
}

ジェネリックオブジェクトを取得し、キャストを行い、キャストするインターフェイスが実装されているかどうかを確認する場合、コードは次のとおりです。

 var myCastedObject = myObject as IMyInterface;

    if(myCastedObject != null) {
      // object myObject implements IMyInterface
    }
0
user11773533