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 ()?


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

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


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

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ą.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.