virtual
, override
, abstract
. Jak wykorzystując refleksję dobrać się do tych danych ? Nie jest to niestety takie proste. Dla metod mamy dostępne właściwości
MethodInfo.IsVirtual
, MethodInfo.IsAbstract
. Informacje o właściwościach są bardzo ubogie. Całe wnioskowanie musimy przeprowadzić w oparciu o metody
PropertyInfo.GetGetMethod
i PropertyInfo.GetSetMethod
do których dostęp możemy też uzyskać poprzez PropertyInfo.GetAccessors
. Wszystkie trzy metody mają przeładowaną wersję za pomocą których dobieramy się do metod niepublicznych. Tak więc analiza właściwości sprowadza się do analizy jednej z jej metod: getter-a albo setter-a. Nie trzeba analizować obu gdyż modyfikatory typu virtual
, override
, abstract
są nakładane na właściwość.Do ustalenia metody bazowej służy
MethodInfo.GetBaseDefinition
. W przypadku braku takowej funkcja nie zwraca null
tylko samą siebie.Do ustalenia typu w którym metoda została zdefiniowana służy
MethidInfo.DeclaringType
. Jest jeszcze MethidInfo.ReflectedType
, który zwraca typ z którego dana metoda została pobrana. Np. jeśli jest to metoda publiczna zdefiniowana w klasie bazowej A
, a pobrana z klasy podrzędnej B
to te dwie wartości będą różne. Co więcej porównanie metod da inne wyniki.Całość ogólnie tworzy mętny obraz. Sam nie wiem czy podane niżej rozwiązanie obejmuje wszystkie przypadki i czy nie ma jakiś wyjątków. Cała refleksja w C# jest potężna, ale jak w nią wnikamy pojawia się mnóstwo problemów. Brakuje podanych niżej metod. Metod na porównanie czy elementy są takie same, niezależnie od różnicy
ReflectedType
, brakuje rozbudowanej PropertyInfo
, tak by nie trzeba było analizować jej metody getter-a i setter-a. Bardzo trudno ustalić, że metoda interfejsu została zadeklarowana bez użycia virtual
. Bardzo trudno ustalić czy metoda została zadeklarowana przy pomocy new
. Nie da się w żaden sposób powiązać właściwości automatycznej z polem prywatnym. I pewnie jeszcze wiele innych.Moja wersja metod, która na obecny czas działają:
////// With virtual keyword. Also includes interface implementations even without /// virtual keyword. /// /// ///public static bool IsVirtual(this MethodInfo a_mi) { return a_mi.IsVirtual && !a_mi.IsAbstract && !a_mi.IsOverriden(); } /// /// With abstract keyword. /// /// ///public static bool IsAbstract(this MethodInfo a_mi) { return a_mi.IsAbstract; } /// /// With override keyword. /// /// ///public static bool IsOverriden(this MethodInfo a_mi) { return a_mi.DeclaringType != a_mi.GetBaseDefinition().DeclaringType; } /// /// With virtual keyword. Also includes interface implementations /// even without virtual keyword. /// /// ///public static bool IsVirtual(this PropertyInfo a_pi) { if (a_pi.GetAccessors(true).Length == 0) return false; return a_pi.GetAccessors(true)[0].IsVirtual(); } /// /// With abstract keyword. /// /// ///public static bool IsAbstract(this PropertyInfo a_pi) { if (a_pi.GetAccessors(true).Length == 0) return false; return a_pi.GetAccessors(true)[0].IsAbstract(); } /// /// With override keyword. /// /// ///public static bool IsOverriden(this PropertyInfo a_pi) { if (a_pi.GetAccessors(true).Length == 0) return false; return a_pi.GetAccessors(true)[0].IsOverriden(); }
Brak komentarzy:
Prześlij komentarz