C#
のリフレクションは、あるSystem.Type
型が何らかのインターフェースをモデル化しているかどうかを判断する方法を提供しますか?
public interface IMyInterface {}
public class MyType : IMyInterface {}
// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);
あなたは私の頭の上からいくつかの選択肢があります
typeof(IMyInterface).IsAssignableFrom(typeof(MyType))
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
一般的なインターフェースでは、少し違います。
typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))
Type.IsAssignableFrom
を使います。
typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());
または
typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
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呼び出しで使用されます)。
今やりました:
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
をフリップフロップします。
他の誰かがすでに述べたように:ベンジャミン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>();
最適なパフォーマンスを得るための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);
IsAssignableFrom
はTypeInfo
に移動しました:
typeof(ISMSRequest).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo());
正しい答えは
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
どうですか?
typeof(IWhatever).GetTypeInfo().IsInterface
一般的なインターフェースIMyInterface<T>
がある場合、これは常にfalse
を返します。
typeof(IMyInterface<>).IsAssignableFrom(typeof(MyType)) /* ALWAYS FALSE */
これもうまくいきません。
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface<>)) /* ALWAYS FALSE */
しかし、MyType
がIMyInterface<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<>)
タイプまたはインスタンスがある場合、それらが特定のインターフェースをサポートしているかどうかを簡単に確認できます。
オブジェクトが特定のインターフェイスを実装しているかどうかをテストするには:
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
}