Wie bekommt man einen Eigenschaftsnamen eines gegebenen Typs stark typisiert?

.net c# expression-trees reflection

Frage

Ich möchte in der Lage sein, den Namen einer Eigenschaft eines Typs unter Verwendung einer stark typisierten Syntax abzurufen. Ich habe bereits eine Funktion bekommen, um einen Eigenschaftsnamen einer Instanz zu erhalten:

public static string PropertyName<T, TReturn>(this T obj, Expression<Func<T, TReturn>> property) where T : class 
{
    MemberExpression body = (MemberExpression) property.Body;
    if (body == null) throw new ArgumentException("The provided expression did not point to a property.");       
    return body.Member.Name;
}

Was kann man so nennen:

Car car = new Car();
car.PropertyName(x => x.Wheels) //returns "Wheels"

Ich versuche, eine andere Funktion zu erstellen, die Folgendes unterstützen könnte:

Type t = Typeof(Car);
t.PropertyName(x => x.Wheels) //should return "Wheels"

Oder einfach (noch besser!):

Car.PropertyName(x => x.Wheels)

Wie würde ich darüber gehen?

Akzeptierte Antwort

Sie können Ihre Methode neu schreiben, um sie zu verwenden, ohne eine Instanz zu erstellen:

var prop = ReflectionHelper.PropertyName<Car>(x => x.Wheels);

weil du nicht obj inside verwendest, weil du es nicht brauchst:

public static class ReflectionHelper
{
    public static string PropertyName<T>(Expression<Func<T, object>> property) where T : class 
    {
        MemberExpression body = (MemberExpression)property.Body;
        return body.Member.Name;
    }
}

Beachten Sie, dass der Rückgabetyp nicht stark typisiert sein muss, sondern nur ein object .


Beliebte Antwort

Das @abatishchev-Beispiel funktioniert nur, wenn Wheels ein Referenztyp ist.

Wenn Sie folgendes haben

public class Car
{
   public int ID;
}

Und du versuchst das anzurufen

var prop = ReflectionHelper.PropertyName<Car>(x => x.ID);

Sie erhalten die folgende Ausnahme

InvalidCastException: Das Objekt vom Typ 'System.Linq.Expressions.UnaryExpression' kann nicht in 'System.Linq.Expressions.MemberExpression' umgewandelt werden.

Ich denke, das hat mit der Tatsache zu tun, dass Sie einen Werttyp an den Ausdruck übergeben, sodass er in ein Objekt eingebettet werden muss. Wenn Sie einen Referenztyp übergeben, muss er nicht in einem Objekt enthalten sein.

Was Sie stattdessen tun können, ist folgendes:

var prop = ReflectionHelper.PropertyName((Car x) => x.Wheels);

public static class ReflectionHelper
{
    public static string PropertyName<T, P>(Expression<Func<T, P>> property) 
        where T : class 
    {
        MemberExpression body = (MemberExpression)property.Body;
        return body.Member.Name;
    }
}


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow