Ich bin kürzlich wieder einmal über ein kleines Problem gestoßen.
Es kommt ja immer wieder mal vor, dass man Properties per Reflection auslesen muss oder noch besser, dass man Werte von Properties verändern muss. Alles an sich kein Problem, wenn man sich mal ein bisschen mit Reflection beschäftigt hat.
Hier ein kleines Beispiel:

abstract class BaseClass
{
	public int Id {get; set;}
}

class ChildClass01:BaseClass
{
	public string ChildClassProperty01 {get; set;}
	public string ChildClassProperty02 {get; set;}
}

Um jetzt zum Beispiel an die Property „Id“ zu kommen, benötigt man nur folgenden Code:

typeof(ChildClass01).GetProperty("Id");

Jetzt ist aber sicherlich schon aufgefallen, dass ich die Property in eine abstrakte Basisklasse gesteckt habe. Das ist Absicht und – wie man am obigen Beispiel sieht – auch kein Problem. Das Problem kommt jetzt erst, wenn man eine zweite Childklasse einführt, die diese Property „Id“ mit new neu einführt:

class ChildClass02:BaseClass
{
	public new Guid Id {get; set;}
	public string ChildClassProperty01 {get; set;}
	public string ChildClassProperty02 {get; set;}
}

Es gibt ja öfter solche Fälle, gerade wenn man mit Legacy-Code arbeitet, dass sich einfach nicht alle Objekte an die Standards halten wollen. Aber auch in so einem Fall soll man dann natürlich weiterhin arbeiten können.
Wenn wir jetzt auf dem gleichen Weg wie vorher versuchen, an die Property zu kommen, werden wir eine „AmbiguousMatchException“ bekommen. AmbiguousMatchException bedeutet soviel wie „Mehrdeutige Übereinstimmung gefunden“.
Schauen wir uns mal an, wie es dazu kommt:

typeof(ChildClass02).GetProperties()
    .Where(n => 
        n.Name.Equals("Id"))
    .Count();

Das gibt tatsächlich zwei zurück. Reflection findet also nicht nur die Property aus der angegebenen Klasse sondern auch noch die überschriebene Property aus der Basisklasse. Man müsste jetzt also irgendwie unterscheiden können, in welcher echten Klasse diese Property definiert wurde und dann die entsprechende Property verwenden.
Das Zauberwort heißt in diesem Fall „DeclaringType„. Diese Property im PropertyInfo-Objekt gibt an, wo diese Property definiert wurde.
Um also zu unserer gesuchten Property zu gelangen, würde der Code folgendermaßen aussehen:

typeof(ChildClass02).GetProperties()
    .Where(n => 
        n.Name.Equals("Id") && 
        n.DeclaringType == typeof(ChildClass02));

Damit kann man dann auf jeden Fall auf Nummer sicher gehen. Es gibt nur noch ein kleines Problem bei der Sache: Was passiert, wenn man noch eine Klasse erstellt, die von ChildClass02 ableitet. Diese Klasse überschreibt jetzt nicht wieder die Property „Id„, sondern ist eine ganz nochmal Unterklasse. In den meisten Situationen verwendet man Reflection immer von der untersten Stelle ab, also dann von dieser neuen Klasse. Wenn man jetzt auf DeclaringType einschränkt, hat man aber das Problem, dass man da explizit die Überklasse angeben muss. Wird also dann schwierig, wenn man vollkommen dynamisch programmieren will. Aber auch dafür gibt es eine Lösung und die nennt sich Rekursion:

PropertyInfo GetProperty(Type type, string name)
{
    PropertyInfo result = type.GetProperties()
        .Where(n=>
            n.Name.Equals(name) &&
            n.DeclaringType.Equals(type))
        .SingleOrDefault();
    if (result == null)
        return GetProperty(type.BaseType, name);
    return result;
}

und daraus könnte man dann auch noch eine schöne Extension-Methode machen, die das Ganze noch bequemer zu verwenden macht.