2011-08-11

Sprawdzenie czy właściwość wywodzi się z innej właściwości.

Metoda ta była mi potrzebna do wyciągnięcia z klasy wszystkich właściwości. W tym celu trzeba przejść przez wszystkie podtypu typu dla którego wyciągamy informację, dla każdego z nich trzeba pobrać wszystkie właściwości i wykluczyć powtarzające.

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 IEnumerable GetBaseDefinitions(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