Jak sprawdzić, czy obiekt ma określoną metodę / właściwość?

155

Może używasz wzorca dynamicznego? Możesz wywołać dowolną metodę / właściwość za pomocą dynamicznego słowa kluczowego, prawda? Jak na przykład sprawdzić, czy metoda istnieje przed wywołaniem myDynamicObject.DoStuff ()?

Louis Rhys
źródło
Jaki jest typ myDynamicObject ? Czy jest to klasa pochodna DynamicObject?
Cheng Chen,
coś zadeklarowanego za pomocą dynamicznego słowa kluczowego
Louis Rhys,

Odpowiedzi:

224

Możesz napisać coś takiego:

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

Edycja: możesz nawet wykonać metodę rozszerzenia i używać jej w ten sposób

myObject.HasMethod("SomeMethod");
Julien
źródło
GetType () zwróci typ środowiska uruchomieniowego? (czyli nie obiekt?)
Louis Rhys,
2
tak, GetType () zwraca bieżący typ, podczas gdy typeof () zwróci obiekt.
Julien
1
Zgodnie z dokumentacją GetType () zwróci „Dokładny typ środowiska wykonawczego bieżącej instancji”.
tzup
Ponadto metoda rozszerzenia musiałaby być statyczna.
Fraser
9
Wolę pisać: objectToCheck.GetType (). GetMethod (methodName)! = Null
efirat
85

poprzez refleksję

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

Podobnie jest z metodami

Stecya
źródło
Miły. Możesz również wykonać GetMethod w pętli, aby uzyskać odpowiednią zdefiniowaną właściwość.
Jnr
Przydatne do przeglądania połączonych list kontrolek interfejsu użytkownika i ich rodziców
Chicowitz,
W GetType()tym jest metoda GetProperties(). Zwraca tablicę PropertyInfo. Ale jak mogę użyć GetProperties()metody?
Yogesh Patel
43

To stare pytanie, ale właśnie na nie wpadłem. Type.GetMethod(string name)zgłosi AmbiguousMatchException, jeśli istnieje więcej niż jedna metoda o tej nazwie, więc lepiej obsłużmy ten przypadek

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
źródło
18

Czy nie byłoby lepiej nie używać do tego żadnych typów dynamicznych i pozwolić swojej klasie zaimplementować interfejs. Następnie możesz sprawdzić w czasie wykonywania, czy obiekt implementuje ten interfejs, a zatem ma oczekiwaną metodę (lub właściwość).

public interface IMyInterface
{
   void Somemethod();
}


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

Myślę, że to jedyny właściwy sposób.

Rzecz, do której się odnosisz, to pisanie kaczkowe, co jest przydatne w scenariuszach, w których wiesz już, że obiekt ma metodę, ale kompilator nie może tego sprawdzić. Jest to przydatne na przykład w scenariuszach międzyoperacyjnych modelu COM. (sprawdź ten artykuł)

Jeśli chcesz na przykład połączyć pisanie kaczką z refleksją, myślę, że nie osiągasz celu, jakim jest pisanie kaczką.

Frederik Gheysels
źródło
2
co się stanie, jeśli obiekt może być obiektem udostępnionym przez platformę .NET, a nie mogę zadeklarować, aby cokolwiek zaimplementował?
Louis Rhys,
Jaki jest problem ? Możesz sprawdzić, czy
``
na przykład chcesz sprawdzić, czy w obiekcie istnieje metoda „Dodaj”. ANd obiekt może być List <int> lub inną klasą, która nie jest IEnumerable
Louis Rhys,
3
Być może powinieneś przyjrzeć się skryptowaniu produktu Adobe z COM. To samo wywołanie funkcji może zwrócić całkowicie różne obiekty COM, a według projektu (Adobe) ich jedynym wspólnym przodkiem jest obiekt. Ponadto: jest to powszechny wzorzec w prawie każdym nowoczesnym dynamicznym języku skryptowym (Python, Javascript, skrypt VB, PHP, Lua ... mógłbym kontynuować i kontynuować). To nie jest błąd, to jest funkcja.
Tim Keating,
5
To zapach, ale został stworzony przez Microsoft. Przyjrzyj się kontrolkom WebControl, takim jak Button, LinkButton itp. Oba implementują właściwość OnClientClick, ale powiedzmy ListControl i Panel nie. OnClientClick nie jest zdefiniowany w interfejsie, więc odbicie jest jedyną opcją.
HammerIp