712 Stimmen

Wie man bestimmt, ob ein Typ eine Schnittstelle mit C#-Reflexion implementiert

Bietet Reflexion in C# eine Möglichkeit festzustellen, ob ein bestimmter System.Type ein bestimmtes Interface modelliert?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// sollte 'true' ergeben
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);

12voto

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

Um zu testen, ob ein Objekt eine bestimmte Schnittstelle implementiert:

if(myObject is IMyInterface) {
  // Objekt myObject implementiert IMyInterface
}

Um zu testen, ob ein Typ eine bestimmte Schnittstelle implementiert:

if(typeof(IMyInterface).IsAssignableFrom(typeof(MyType))) {
  // Typ MyType implementiert IMyInterface
}

Wenn Sie ein generisches Objekt haben und sowohl einen Cast als auch eine Überprüfung durchführen möchten, ob die Schnittstelle, zu der Sie casten möchten, implementiert ist, lautet der Code:

 var myCastedObject = myObject as IMyInterface;

    if(myCastedObject != null) {
      // Objekt myObject implementiert IMyInterface
    }

0 Stimmen

Das letzte Beispiel könnte verkürzt werden zu if (myObject ist IMyInterface myCastedObject) { ... }

10voto

toddmo Punkte 18450

Ich habe gerade gemacht:

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

_

Ich wünschte, ich könnte gesagt haben where I : interface, aber interface ist keine generische Parameterbeschränkungsoption. class ist so nah wie es geht.

Verwendung:

if(MyType.Implements())
  MyCollection.Initialize();

Ich habe gerade Implements gesagt, weil das intuitiver ist. Ich bringe IsAssignableFrom immer durcheinander.

_

0 Stimmen

Du könntest return typeof(I).IsInterface && typeof(I).IsAssignableFrom(source); tun, um bei allen "falschen" Verwendungen der Methode false zurückzugeben, das heißt, wenn Sie sie mit einem Klassentyp anstelle eines Schnittstellentyps verwenden, oder werfe alternativ eine Ausnahme, wenn der Typ-Parameter keine Schnittstelle ist. Obwohl man argumentieren könnte, dass eine abgeleitete Klasse ihren Eltern "implementiert" ...

8voto

Goof'Nat' Punkte 6397

Wie bereits von jemand anderem erwähnt wurde: Benjamin Apr 10 '13 um 22:21 Uhr"

Es war wirklich einfach, nicht aufzupassen und die Argumente für IsAssignableFrom durcheinander zu bringen. Ich werde jetzt mit GetInterfaces weitermachen :p –

Nun, ein anderer Ansatz besteht darin, einfach eine kurze Erweiterungsmethode zu erstellen, die in gewissem Maße dem "üblichsten" Denkweise entspricht (und zugegeben, dies ist eine sehr persönliche Entscheidung, um es leicht "natürlicher" zu machen, basierend auf den eigenen Vorlieben):

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

Und warum nicht etwas generischer vorgehen (nun, ich bin mir nicht sicher, ob es wirklich so interessant ist, nun nehme ich einfach eine Prise 'Syntaxzucker'):

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

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

Ich denke, das könnte viel natürlicher sein, aber wieder einmal ist es nur eine Frage sehr persönlicher Meinungen:

var isTrue = michelleType.IsAssignableTo();

4 Stimmen

Gibt es einen Grund, warum du die Implementierung nicht direkt in der Erweiterungsmethode hinzugefügt hast? Klar, das ermöglicht es dir, es auf beide Arten aufzurufen, aber warum würdest du das jemals brauchen?

0 Stimmen

@MarqueIV Es tut mir leid, dass ich fast 2 Jahre später antworte, nun ja, damals war es wohl eine alte schlechte Angewohnheit, Hilfsmethoden in Erweiterungsmethoden zu verpacken, um Code-Wiederholungen zu vermeiden. Ich werde meine Antwort bearbeiten :)

1 Stimmen

@MarqueIV erledigt plus ich habe meine andere schlechte Angewohnheit geändert, nämlich Boolean => bool (ich weiß nicht warum ich früher so strikte "fancy" Codierungsregeln hatte).

7voto

Ben Wilde Punkte 5244

Überarbeitung von Jeffs Antwort für optimale Leistung (Dank Leistungstest von Pierre Arnaud):

var typ = typeof(MyType);
var implementiertInterface = typeof(IMyInterface).IsAssignableFrom(typ) && typ.IsClass;

Um alle Typen zu finden, die ein Interface in einer bestimmten Assembly implementieren:

var Implementierungen = typeof(TypeInTargetAssembly).Assembly.GetTypes()
                          .Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass);

6voto

Diego Punkte 17339

Beachten Sie, dass wenn Sie eine generische Schnittstelle IMyInterface haben, dann wird dies immer false zurückgeben:

  typeof(IMyInterface<>).IsAssignableFrom(typeof(MyType)) /* IMMER FALSCH */

Dies funktioniert auch nicht:

  typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface<>))  /* IMMER FALSCH */

Wenn jedoch MyType IMyInterface implementiert, funktioniert dies und gibt true zurück:

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

Sie werden jedoch wahrscheinlich den Typparameter T zur Laufzeit nicht kennen. Eine etwas umständliche Lösung ist:

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

Jeffs Lösung ist etwas weniger umständlich:

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

Hier ist eine Erweiterungsmethode für Type, die für 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 das oben genannte Linq verwendet, was wahrscheinlich langsamer ist als eine Schleife.)

Sie können dann Folgendes tun:

   typeof(MyType).IsImplementing(IMyInterface<>)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X