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.

Tenpn
quelle

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.

Kevin Kalitowski
quelle
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();
        }
    }
}
Marc Gravell
quelle
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?

Vojislav Stojkovic
quelle
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.

Darin Dimitrov
quelle
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