Niestety
PropertyInfo
niosą bardzo mało informacji w sobie i trzeba odwoływać się do ich metod getter- i setter-a.W pierwszym etapie sprawdzamy, czy te właściwości nie są przypadkiem takie same. Niestety z uwagi na
ReflectedType
nie możemy tak po prostu je porównać. Dalej analizujemy zależności pomiędzy ich metodami ustawiającymi i pobierającymi. Do analizy zależności wykorzystujemy MetohodInfo.GetBaseDefinition (są dwie przeładowane wersje, ta druga z parametrem jest dla nas bardziej użyteczna, gdyż zwraca niepubliczne metody). I tutaj znowu niestety. Jeśli automatyczna właściwość jest zdefiniowana w klasie bazowej jako wirtualna i nadpisana w dwóch kolejnych klasach, to obie nadpisane właściwości wskazują poprzez MetohodInfo.GetBaseDefinitions swoich metod na metody właściwości w klasie wirtualnej. I to zmusiło mnie z prostego sprawdzania, czy MetohodInfo.GetBaseDefinitions jednej jest równe GetBaseDefinitions drugiej do sprawdzenia czy nie mają one jakiejś wspólnej metody bazowej.
Kod:
private static IEnumerableGetBaseDefinitions(this MethodInfo a_mi, bool a_with_this = false) { if (a_with_this) yield return a_mi; MethodInfo t = a_mi; while ((t.GetBaseDefinition() != null) && (t.GetBaseDefinition() != t)) { t = t.GetBaseDefinition(); yield return t; } } private static bool ContainsAny (this IEnumerable a_enumerable, IEnumerable a_values) { return a_enumerable.Intersect(a_values).Any(); } private static bool IsDerivedFrom(this PropertyInfo a_pi, PropertyInfo a_base, bool a_with_this = false) { if (a_pi.Name != a_base.Name) return false; if (a_pi.PropertyType != a_base.PropertyType) return false; if (!a_pi.GetIndexParameters().SequenceEqual(a_base.GetIndexParameters())) return false; if (a_pi.DeclaringType == a_base.DeclaringType) return a_with_this; MethodInfo m1 = a_pi.GetGetMethod(true); MethodInfo m3 = a_base.GetGetMethod(true); if ((m1 != null) && (m3 != null)) { if (m1.GetBaseDefinitions().ContainsAny(m3.GetBaseDefinitions(true))) return true; } else if ((m1 != null) || (m3 != null)) return false; MethodInfo m2 = a_pi.GetSetMethod(true); MethodInfo m4 = a_base.GetSetMethod(true); if ((m2 != null) && (m4 != null)) { if (m2.GetBaseDefinitions().ContainsAny(m4.GetBaseDefinitions(true))) return true; } else if ((m2 != null) || (m4 != null)) return false; return false; }
Brak komentarzy:
Prześlij komentarz