W mojej klasie jest grupa prywatnych metod i muszę wywoływać jedną dynamicznie na podstawie wartości wejściowej. Zarówno kod wywołujący, jak i metody docelowe znajdują się w tej samej instancji. Kod wygląda następująco:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
W takim przypadku GetMethod()
nie zwróci metod prywatnych. Co BindingFlags
muszę dostarczyć, aby GetMethod()
mógł znaleźć metody prywatne?
c#
.net
reflection
private-methods
Jeromy Irvine
źródło
źródło
BindingFlags.NonPublic
nie zwracaprivate
metody .. :(BindingFlags.Instance
tak samo, jakBindingFlags.NonPublic
dla metod niestatycznych.non-static
aprivate
klasa jest dziedziczona zSystem.Web.UI.Page
.. to i tak mnie oszukuje .. nie znalazłem powodu .. :(BindingFlags.FlattenHierarchy
umożliwi pobranie metod z klas nadrzędnych do instancji.BindingFlags.NonPublic
sam nie zwróci żadnych wyników. Jak się okazuje, połączenie z tymBindingFlags.Instance
rozwiązuje problem.źródło
internal
funkcjiA jeśli naprawdę chcesz wpaść w kłopoty, ułatw to wykonanie, pisząc metodę rozszerzenia:
I użycie:
źródło
Firma Microsoft niedawno zmodyfikowała interfejs API odbicia, przez co większość tych odpowiedzi stała się nieaktualna. Następujące elementy powinny działać na nowoczesnych platformach (w tym Xamarin.Forms i UWP):
Lub jako metoda rozszerzenia:
Uwaga:
Jeśli pożądany sposób w nadklasą ogólne muszą być wyraźnie określone w rodzaju nadrzędnej.
obj
T
Jeśli metoda jest asynchroniczna, możesz użyć
await (Task) obj.InvokeMethod(…)
.źródło
GetDeclareMethod()
jest przeznaczony do użycia tylko do publicznej metody.Czy jesteś absolutnie pewien, że nie da się tego zrobić poprzez dziedziczenie? Refleksja to ostatnia rzecz, na którą powinieneś zwrócić uwagę przy rozwiązywaniu problemu. Utrudnia to refaktoryzację, zrozumienie kodu i automatyczną analizę.
Wygląda na to, że powinieneś mieć po prostu klasę DrawItem1, DrawItem2 itd., Która przesłania twoją metodę dynMethod.
źródło
Refleksja szczególnie na temat członków prywatnych jest błędna
Odbicie członków prywatnych łamie zasadę enkapsulacji, a tym samym naraża Twój kod na:
Co jeśli i tak muszę to zrobić?
Zdarzają się przypadki, w których zależysz na stronie trzeciej lub potrzebujesz nieosłoniętego interfejsu API, musisz się zastanowić. Niektórzy używają go również do testowania posiadanych klas, ale nie chcą zmieniać interfejsu, aby dać dostęp do wewnętrznych elementów tylko na potrzeby testów.
Jeśli to zrobisz, zrób to dobrze
Aby złagodzić problem łatwej do złamania, najlepiej jest wykryć potencjalną przerwę, testując w testach jednostkowych, które działałyby w kompilacji ciągłej lub podobnej. Oczywiście oznacza to, że zawsze używasz tego samego zestawu (który zawiera członków prywatnych). Jeśli używasz obciążenia dynamicznego i odbicia, lubisz bawić się ogniem, ale zawsze możesz uchwycić wyjątek, który może wywołać połączenie.
W najnowszych wersjach .Net Framework CreateDelegate pokonał 50-krotnie metodę MethodInfo:
draw
Połączenia będzie około 50x szybciej niżMethodInfo.Invoke
wykorzystaniadraw
jako standardFunc
tak:Sprawdź mój post, aby zobaczyć wyniki testów wywoływania różnych metod
źródło
Czy nie możesz mieć innej metody rysowania dla każdego typu, który chcesz narysować? Następnie wywołaj przeciążoną metodę Draw przekazującą obiekt typu itemType, który ma zostać narysowany.
Twoje pytanie nie wyjaśnia, czy itemType rzeczywiście odnosi się do obiektów różnych typów.
źródło
Myślę, że możesz przekazać to
BindingFlags.NonPublic
tam , gdzie jestGetMethod
metoda.źródło
Wywołuje dowolną metodę pomimo poziomu ochrony w instancji obiektu. Cieszyć się!
źródło
Przeczytaj tę (dodatkową) odpowiedź (która czasami jest odpowiedzią), aby zrozumieć, dokąd to zmierza i dlaczego niektórzy ludzie w tym wątku narzekają, że „wciąż nie działa”
Napisałem dokładnie ten sam kod, co jedną z odpowiedzi tutaj . Ale wciąż miałem problem. Położyłem punkt przerwania
Wykonało się, ale
mi == null
I tak się zachowywało, dopóki nie „przebudowałem” wszystkich zaangażowanych projektów. Testowałem jedno urządzenie, gdy metoda odbicia znajdowała się w trzecim. To było całkowicie mylące, ale użyłem Immediate Window, aby odkryć metody i odkryłem, że prywatna metoda, którą próbowałem przetestować, miała starą nazwę (zmieniłem jej nazwę). To powiedziało mi, że stary zestaw lub PDB wciąż tam jest, nawet jeśli buduje się projekt testu jednostkowego - z jakiegoś powodu projekt, którego testy nie zbudował. „przebudowa” działała
źródło
BindingFlags.NonPublic
źródło