Jak uzyskać PropertyInfo o określonej nieruchomości?


82

Chcę uzyskać PropertyInfo dla określonej właściwości. Mógłbym użyć:

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

Ale musi być sposób na zrobienie czegoś podobnego do

typeof(MyProperty) as PropertyInfo

Jest tu? A może utknąłem podczas porównywania ciągów znaków niebezpiecznych?

Twoje zdrowie.

Odpowiedzi:


61

Możesz użyć nowego nameof()operatora, który jest częścią C # 6 i jest dostępny w programie Visual Studio 2015. Więcej informacji tutaj .

Na przykład użyłbyś:

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

Kompilator skonwertuje nameof(MyObject.MyProperty)na ciąg „MyProperty”, ale zyskasz możliwość refaktoryzacji nazwy właściwości bez konieczności pamiętania o zmianie ciągu, ponieważ Visual Studio, ReSharper i tym podobne potrafią refaktoryzować nameof()wartości.


1
Jeśli byłoby to trochę jaśniejsze, gdyby twój przykład zaczął się od PropertyInfo result =zamiast var result =.
DavidRR

134

Istnieje sposób .NET 3.5 z lambdami / Expression, który nie używa łańcuchów ...

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();
        }
    }
}

Niezłe rozwiązanie, ale niestety nie używam .NET3.5. Wciąż, zaznacz!
tenpn

1
W wersji 2.0 odpowiedź Vojislava Stojkovica jest najbliższa, jaką można uzyskać.
Marc Gravell

4
jedno pytanie: dlaczego przed wyodrębnieniem właściwości .Body istnieje test „body is LambdaExpression”? Czy selector nie jest zawsze wyrażeniem LambdaExpression?
tigrou

@tigrou prawdopodobnie tylko przeoczenie i być może pożyczyłem istniejący kod, który działał przeciwko właśnieExpression
Marc Gravell

@MarcGravell ta implementacja nie jest zbyt rozsądna. Nie otrzymasz poprawnych informacji o nieruchomości w przypadku PropertyHelper<Derived>.GetProperty(x => x.BaseProperty);. Zobacz stackoverflow.com/questions/6658669/ ...
nawfal

13

Możesz to zrobić:

typeof(MyObject).GetProperty("MyProperty")

Jednak ponieważ C # nie ma typu „symbol”, nie ma nic, co pomoże uniknąć używania ciągu. Nawiasem mówiąc, dlaczego nazywasz ten typ niebezpiecznym?


38
Ponieważ nie jest oceniany w czasie kompilacji? Gdybym zmienił nazwę własności lub wpisał ciąg znaków, nie wiedziałbym, dopóki kod nie zostanie uruchomiony.
tenpn

1

Odbicie jest używane do oceny typu w czasie wykonywania. Dlatego stałych łańcuchowych nie można zweryfikować w czasie kompilacji.


5
Tego właśnie stara się uniknąć OP. Nie jestem pewien, czy to odpowiada na pytanie.
nawfal

Dobra uwaga dotycząca czasu kompilacji w porównaniu z czasem wykonywania i pierwotnym zamiarem OP, chociaż unikanie ciągów zakodowanych na stałe wydaje się być najczystszym rozwiązaniem - unika możliwości literówek, pozwala na łatwiejszą refaktoryzację i zapewnia czystszy styl kodu.
Brian Sweeney,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.