Wie erhalte ich die PropertyInfo einer bestimmten Eigenschaft?


79

Ich möchte die PropertyInfo für eine bestimmte Eigenschaft erhalten. Ich könnte benutzen:

foreach(PropertyInfo p in typeof(MyObject).GetProperties())
{
    if ( p.Name == "MyProperty") { return p }
}

Aber es muss einen Weg geben, etwas Ähnliches zu tun

typeof(MyProperty) as PropertyInfo

Gibt es? Oder bin ich nicht in der Lage, einen typsicheren Zeichenfolgenvergleich durchzuführen?

Prost.

Antworten:


59

Sie können den neuen nameof()Operator verwenden, der Teil von C # 6 ist und in Visual Studio 2015 verfügbar ist. Weitere Informationen finden Sie hier .

Für Ihr Beispiel würden Sie verwenden:

PropertyInfo result = typeof(MyObject).GetProperty(nameof(MyObject.MyProperty));

Der Compiler konvertiert nameof(MyObject.MyProperty)in die Zeichenfolge "MyProperty". Sie profitieren jedoch davon, dass Sie den Eigenschaftsnamen umgestalten können, ohne daran denken zu müssen, die Zeichenfolge zu ändern, da Visual Studio, ReSharper und dergleichen wissen, wie nameof()Werte umgestaltet werden.


1
Wenn wäre wohl ein bisschen klarer, wenn Ihr Beispiel mit PropertyInfo result =statt begann var result =.
DavidRR

133

Es gibt eine .NET 3.5-Methode mit Lambdas / Expression, die keine Zeichenfolgen verwendet ...

using System;
using System.Linq.Expressions;
using System.Reflection;

class Foo
{
    public string Bar { get; set; }
}
static class Program
{
    static void Main()
    {
        PropertyInfo prop = PropertyHelper<Foo>.GetProperty(x => x.Bar);
    }
}
public static class PropertyHelper<T>
{
    public static PropertyInfo GetProperty<TValue>(
        Expression<Func<T, TValue>> selector)
    {
        Expression body = selector;
        if (body is LambdaExpression)
        {
            body = ((LambdaExpression)body).Body;
        }
        switch (body.NodeType)
        {
            case ExpressionType.MemberAccess:
                return (PropertyInfo)((MemberExpression)body).Member;
            default:
                throw new InvalidOperationException();
        }
    }
}

Gute Lösung, aber leider verwende ich nicht .NET3.5. Trotzdem ankreuzen!
Tenpn

1
In 2.0 ist Vojislav Stojkovics Antwort die naheliegendste, die Sie bekommen können.
Marc Gravell

4
Eine Frage: Warum gibt es einen Test für "body is LambdaExpression", bevor die .Body-Eigenschaft extrahiert wird? Ist Selektor nicht immer ein LambdaExpression?
Tigrou

@tigrou möglicherweise nur ein Versehen, und vielleicht leihe ich vorhandenen Code, der gegen nur funktioniertExpression
Marc Gravell

@MarcGravell diese Implementierung ist nicht sehr solide. Sie erhalten im Falle von nicht die richtigen Eigenschaftsinformationen PropertyHelper<Derived>.GetProperty(x => x.BaseProperty);. Siehe stackoverflow.com/questions/6658669/…
nawfal

12

Du kannst das:

typeof(MyObject).GetProperty("MyProperty")

Da C # jedoch keinen "Symbol" -Typ hat, hilft Ihnen nichts dabei, die Verwendung von Zeichenfolgen zu vermeiden. Warum nennst du das übrigens typunsicher?


38
Weil es zur Kompilierungszeit nicht ausgewertet wird? Wenn ich meinen Eigenschaftsnamen ändern oder die Zeichenfolge tippen würde, würde ich es nicht wissen, bis der Code ausgeführt wird.
Tenpn

1

Die Reflexion wird zur Bewertung des Laufzeittyps verwendet. Daher können Ihre Zeichenfolgenkonstanten zur Kompilierungszeit nicht überprüft werden.


5
Das versucht OP zu vermeiden. Ich bin mir nicht sicher, ob dies die Frage beantwortet.
Nawfal

Ein guter Punkt in Bezug auf die Kompilierungszeit im Vergleich zur Laufzeit und die ursprüngliche Absicht des OP, obwohl das Vermeiden von fest codierten Zeichenfolgen immer noch die sauberste Lösung zu sein scheint - vermeidet die Möglichkeit von Tippfehlern, erleichtert das Refactoring und sorgt für einen saubereren Codestil.
Brian Sweeney
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.