Jak mówi tytuł: Czy odbicie może dać nazwę aktualnie wykonywanej metody.
Nie jestem skłonny zgadywać z powodu problemu Heisenberga. Jak wywołać metodę, która poinformuje cię o bieżącej metodzie bez zmiany jej aktualnej metody? Ale mam nadzieję, że ktoś może udowodnić, że się mylę.
Aktualizacja:
- Część 2: Czy można tego również użyć do przeszukiwania kodu wewnątrz właściwości?
- Część 3: Jak wyglądałby występ?
Ostateczny wynik
Dowiedziałem się o MethodBase.GetCurrentMethod (). Dowiedziałem się również, że nie tylko mogę utworzyć ślad stosu, ale mogę także stworzyć dokładnie tę klatkę, której potrzebuję, jeśli chcę.
Aby użyć tego wewnątrz właściwości, wystarczy wziąć .Substring (4), aby usunąć „set_” lub „get_”.
.net
reflection
Joel Coehoorn
źródło
źródło
Odpowiedzi:
Począwszy od .NET 4.5 możesz także używać [CallerMemberName]
Przykład: ustawiacz właściwości (w odpowiedzi na część 2):
Kompilator dostarczy pasujące literały łańcuchowe w miejscach wywołań, więc w zasadzie nie ma narzutu wydajności.
źródło
StackFrame(1)
metody opisanej w innych odpowiedziach do rejestrowania, która wydawała się działać, dopóki Jitter nie zdecydował się na wprowadzenie funkcji inline. Nie chciałem dodawać atrybutu, aby zapobiec wstawianiu ze względu na wydajność. Zastosowanie[CallerMemberName]
podejścia rozwiązało problem. Dzięki!OnPropertyChanged("SomeProperty")
i nieOnPropertyChanged("SetProperty")
W przypadku
async
metod innych niż metody można użyćhttps://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.getcurrentmethod
Pamiętaj, że dla
async
metod zwróci „MoveNext”.źródło
async
metody najprawdopodobniej otrzymasz „MoveNext” jako nazwę metody.Fragment dostarczony przez Lexa był trochę długi, więc wskazuję na ważną część, ponieważ nikt inny nie zastosował dokładnie tej samej techniki:
Powinno to zwrócić identyczne wyniki do metody MethodBase.GetCurrentMethod (). Nazwa techniki, ale nadal warto ją wskazać, ponieważ mogłem ją zaimplementować raz we własnej metodzie przy użyciu indeksu 1 dla poprzedniej metody i wywołać ją z wielu różnych właściwości. Ponadto zwraca tylko jedną ramkę, a nie cały ślad stosu:
To też jedna linijka;)
źródło
Wypróbuj to w metodzie Main w pustym programie konsoli:
Dane wyjściowe konsoli:
Main
źródło
Tak, zdecydowanie.
Jeśli chcesz manipulować obiektem, używam funkcji takiej jak ta:
Ta linia:
Podchodzi do ramki stosu, aby znaleźć metodę wywołującą, a następnie używamy refleksji, aby uzyskać wartości informacji o parametrach przekazane do niej dla ogólnej funkcji raportowania błędów. Aby uzyskać bieżącą metodę, po prostu użyj zamiast tego bieżącej ramki stosu (1).
Jak powiedzieli inni dla obecnej nazwy metod, możesz także użyć:
Wolę chodzić po stosie, ponieważ jeśli spojrzysz wewnętrznie na tę metodę, po prostu tworzy StackCrawlMark. Bezpośrednie adresowanie stosu wydaje mi się wyraźniejsze
Po wersji 4.5 możesz teraz użyć [CallerMemberNameAttribute] jako części parametrów metody, aby uzyskać ciąg nazwy metody - może to pomóc w niektórych scenariuszach (ale tak naprawdę w powyższym przykładzie)
Wydawało się, że jest to głównie rozwiązanie dla obsługi INotifyPropertyChanged, gdzie wcześniej ciągi znaków były zaśmiecone przez cały kod zdarzenia.
źródło
Porównywanie sposobów uzyskania nazwy metody - przy użyciu dowolnej konstrukcji czasowej w LinqPad:
KOD
WYNIKI
odbicie odbicie
stacktrace stacktrace
inlineconant inlineconstant
stała stała
wyrażenie e => e.expr ()
exprmember exprmember
Callermember Main
Zauważ, że metody
expr
icallermember
nie są całkiem „właściwe”. I tam pojawia się powtórzenie powiązanego komentarza, że odbicie jest ~ 15 razy szybsze niż stacktrace.źródło
EDYCJA: MethodBase jest prawdopodobnie lepszym sposobem na uzyskanie metody, w której się znajdujesz (w przeciwieństwie do całego stosu wywołań). Nadal jednak martwię się o inline.
Możesz użyć StackTrace w ramach metody:
I spojrzenie na ramki:
Należy jednak pamiętać, że jeśli metoda jest wbudowana, nie będziesz w metodzie, którą uważasz za swoją. Możesz użyć atrybutu, aby zapobiec wstawianiu:
źródło
new StackTrace(true)
zamiastnew StackTrace(false)
. Ustawienie tej wartościtrue
spowoduje, że ślad stosu podejmie próbę przechwycenia nazwy pliku, numeru linii itp., Co może spowolnić to wywołanie. W przeciwnym razie ładna odpowiedźNajprostszym sposobem postępowania jest:
Jeśli element System.Reflection jest zawarty w bloku używającym:
źródło
Co powiesz na to:
źródło
Myślę, że powinieneś być w stanie to uzyskać, tworząc StackTrace . Lub, jak wspominają @ edg i @ Lars Mæhlum , MethodBase. GetCurrentMethod ()
źródło
Spróbuj tego...
źródło
Właśnie zrobiłem to z prostą klasą statyczną:
następnie w kodzie:
źródło
źródło