Wie überprüfe ich, ob ein Objekt eine bestimmte Methode / Eigenschaft hat?

155

Verwenden Sie vielleicht ein dynamisches Muster? Sie können jede Methode / Eigenschaft mit dem dynamischen Schlüsselwort aufrufen, oder? Wie kann ich überprüfen, ob die Methode vorhanden ist, bevor ich beispielsweise myDynamicObject.DoStuff () aufrufe?

Louis Rhys
quelle
Was ist der Typ von myDynamicObject ? Ist es eine Klasse abgeleitet von DynamicObject?
Cheng Chen
etwas mit dem dynamischen Schlüsselwort deklariert
Louis Rhys

Antworten:

224

Sie könnten so etwas schreiben:

public static bool HasMethod(this object objectToCheck, string methodName)
{
    var type = objectToCheck.GetType();
    return type.GetMethod(methodName) != null;
} 

Bearbeiten: Sie können sogar eine Erweiterungsmethode ausführen und diese so verwenden

myObject.HasMethod("SomeMethod");
Julien
quelle
GetType () gibt den Laufzeittyp zurück? (dh kein Objekt?)
Louis Rhys
2
Ja, GetType () gibt den laufenden Typ zurück, während typeof () ein Objekt zurückgeben würde.
Julien
1
Laut den Dokumenten gibt GetType () "den genauen Laufzeittyp der aktuellen Instanz" zurück.
Zup
Außerdem müsste die Erweiterungsmethode statisch sein.
Fraser
9
Ich schreibe lieber: objectToCheck.GetType (). GetMethod (methodName)! = Null
efirat
85

über Reflexion

 var property = object.GetType().GetProperty("YourProperty")
 property.SetValue(object,some_value,null);

Ähnliches gilt für Methoden

Stecya
quelle
Nett. Sie können die GetMethod auch in einer Schleife ausführen, um die entsprechende definierte Eigenschaft abzurufen.
Jnr
Nützlich zum Durchlaufen verknüpfter Listen von UI-Steuerelementen und deren Eltern
Chicowitz
In GetType()gibt es Methode wie GetProperties(). Es wird ein Array von zurückgegeben PropertyInfo. Aber wie kann ich die GetProperties()Methode anwenden?
Yogesh Patel
43

Es ist eine alte Frage, aber ich bin gerade darauf gestoßen. Type.GetMethod(string name)löst eine AmbiguousMatchException aus, wenn es mehr als eine Methode mit diesem Namen gibt, sodass wir diesen Fall besser behandeln können

public static bool HasMethod(this object objectToCheck, string methodName)
{
    try
    {
        var type = objectToCheck.GetType();
        return type.GetMethod(methodName) != null;
    }
    catch(AmbiguousMatchException)
    {
        // ambiguous means there is more than one result,
        // which means: a method with that name does exist
        return true;
    }
} 
esskar
quelle
18

Wäre es nicht besser, dafür keine dynamischen Typen zu verwenden und Ihre Klasse eine Schnittstelle implementieren zu lassen? Anschließend können Sie zur Laufzeit überprüfen, ob ein Objekt diese Schnittstelle implementiert und somit über die erwartete Methode (oder Eigenschaft) verfügt.

public interface IMyInterface
{
   void Somemethod();
}


IMyInterface x = anyObject as IMyInterface;
if( x != null )
{
   x.Somemethod();
}

Ich denke, das ist der einzig richtige Weg.

Sie beziehen sich auf die Ententypisierung, was in Szenarien nützlich ist, in denen Sie bereits wissen, dass das Objekt über die Methode verfügt, der Compiler dies jedoch nicht überprüfen kann. Dies ist beispielsweise in COM-Interop-Szenarien nützlich. (siehe diesen Artikel)

Wenn Sie zum Beispiel Ententypisierung mit Reflexion kombinieren möchten, dann verfehlen Sie meiner Meinung nach das Ziel der Ententypisierung.

Frederik Gheysels
quelle
2
Was ist, wenn das Objekt ein vom .NET Framework bereitgestelltes Objekt sein kann und ich es nicht für die Implementierung deklarieren kann?
Louis Rhys
Was ist das Problem ? Sie können auf die gleiche Weise überprüfen, ob das 'Objekt' ein solches Objekt ist, das vom .NET Framework bereitgestellt wird
Frederik Gheysels
Sie möchten beispielsweise überprüfen, ob ein Objekt eine "Hinzufügen" -Methode enthält. Und das Objekt kann eine Liste <int> oder eine andere Klasse sein, die keine IEnumerable ist
Louis Rhys
3
Vielleicht sollten Sie sich ein Skript für ein Adobe-Produkt mit COM ansehen. Der gleiche Funktionsaufruf kann völlig unterschiedliche COM-Objekte zurückgeben, und nach (Adobe) Design ist das Objekt ihr einziger gemeinsamer Vorfahr. Außerdem: Dies ist ein alltägliches Muster in so ziemlich jeder modernen dynamischen Skriptsprache (Python, Javascript, VB-Skript, PHP, Lua ... ich könnte weiter und weiter machen). Es ist kein Fehler, es ist ein Feature.
Tim Keating
5
Es ist ein Geruch, aber es wurde von Microsoft erstellt. Schauen Sie sich WebControls wie Button, LinkButton usw. an. Beide implementieren die OnClientClick-Eigenschaft, ListControl und Panel jedoch nicht. OnClientClick ist in einer Schnittstelle nicht definiert, daher ist Reflektion die einzige Option.
HammerIp