it-swarm.com.de

Feststellen, ob ein Typ eine Schnittstelle mit C # -Reflexion implementiert

Bietet Reflektion in C# eine Möglichkeit zu bestimmen, ob ein bestimmter System.Type Typ eine Schnittstelle modelliert?

public interface IMyInterface {}

public class MyType : IMyInterface {}

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

Sie haben ein paar Möglichkeiten aus meinem Kopf

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

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

Bei einer generischen Schnittstelle ist das etwas anders.

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

Verwenden Sie Type.IsAssignableFrom :

_typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
_
63
Snea
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());

oder

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

Ich denke, dies ist aus drei Gründen die richtige Version:

1) Es verwendet GetInterfaces und nicht IsAssignableFrom. Es ist schneller, da IsAssignableFrom nach mehreren Überprüfungen GetInterfaces aufruft.
2) Es wird über das lokale Array iteriert, sodass keine Grenzüberprüfungen stattfinden.
3) Es wird der für Type definierte Operator == verwendet, der wahrscheinlich sicherer ist als die Equals-Methode (die der Contains-Aufruf eventuell verwenden wird).

12
Panos Theof

Ich habe gerade getan:

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

Ich wünschte, ich hätte where I : interface sagen können, aber interface ist keine generische Option für Parameterbeschränkungen. class ist so nah wie möglich.

Verwendungszweck:

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

Ich habe gerade Implements gesagt, weil das intuitiver ist. Ich bekomme immer IsAssignableFrom Flip-Flops.

8
toddmo

Wie schon jemand anderes erwähnt: Benjamin 10.04.13 um 22:21 "

Es war sicher einfach, nicht darauf zu achten und die Argumente für IsAssignableFrom rückwärts abzurufen. Ich werde jetzt mit GetInterfaces gehen: p -

Nun, eine andere Möglichkeit besteht darin, eine kurze Erweiterungsmethode zu erstellen, die in gewissem Maße die "üblichste" Denkweise erfüllt (und darin, dass dies eine sehr kleine persönliche Entscheidung ist, die es etwas "natürlicher" macht, je nach den eigenen Vorlieben ):

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

Und warum nicht ein bisschen generischer werden (na ja, ich bin mir nicht sicher, ob es wirklich so interessant ist, na ja, ich gehe davon aus, dass ich nur eine weitere Prise Syntaxing-Zucker übergebe):

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

Ich denke, dass es auf diese Weise viel natürlicher ist, aber auch hier ist es nur eine Frage sehr persönlicher Meinungen:

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

Änderung von Jeffs Antwort für optimale Leistung (dank Leistungstest von Pierre Arnaud):

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

So finden Sie alle Typen, die eine Schnittstelle in einem bestimmten Assembly implementieren:

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

IsAssignableFrom wird jetzt in TypeInfo verschoben:

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

Eine richtige Antwort ist

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

Jedoch,

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

gibt möglicherweise ein falsches Ergebnis zurück, wie der folgende Code mit string und IConvertible zeigt:

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

Ergebnisse:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True
1
EricBDev

Wie wäre es mit

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

Beachten Sie, dass wenn Sie eine generische Schnittstelle IMyInterface<T> haben, diese immer false zurückgibt:

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

Das funktioniert auch nicht:

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

Wenn jedoch MyTypeIMyInterface<MyType> implementiert, funktioniert dies und gibt true zurück:

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

Wahrscheinlich kennen Sie den Typparameter T jedoch zur Laufzeit nicht . Eine etwas hackige Lösung ist:

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

Jeffs Lösung ist ein bisschen weniger hackig:

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

Hier ist eine Erweiterungsmethode für Type, die auf jeden Fall funktioniert:

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

(Beachten Sie, dass im obigen Beispiel linq verwendet wird, das wahrscheinlich langsamer als eine Schleife ist.)

Sie können dann Folgendes tun:

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

Wenn Sie einen Typ oder eine Instanz haben, können Sie leicht überprüfen, ob diese eine bestimmte Schnittstelle unterstützen.

So testen Sie, ob ein Objekt eine bestimmte Schnittstelle implementiert:

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

So testen Sie, ob ein Typ eine bestimmte Schnittstelle implementiert:

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

Wenn Sie ein generisches Objekt haben und eine Umwandlung durchführen möchten sowie prüfen möchten, ob die Schnittstelle, in die Sie die Umwandlung durchführen, implementiert ist, lautet der Code:

 var myCastedObject = myObject as IMyInterface;

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