Come ottenere un nome di proprietà di un determinato tipo fortemente digitato?

.net c# expression-trees reflection

Domanda

Mi piacerebbe essere in grado di recuperare il nome di una proprietà di un tipo usando una sintassi fortemente tipizzata. Ho già ottenuto una funzione per ottenere il nome di una proprietà di un'istanza:

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

Che può essere chiamato così:

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

Sto cercando di creare un'altra funzione in grado di supportare quanto segue:

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

O semplicemente (ancora meglio!):

Car.PropertyName(x => x.Wheels)

Come andrei su questo?

Risposta accettata

Puoi riscrivere il tuo metodo per usarlo senza creare un'istanza:

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

perché non usi obj all'interno perché non ne hai bisogno:

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

Si noti che il tipo restituito non deve essere fortemente digitato, può essere solo un object .


Risposta popolare

L'esempio @abatishchev funziona solo se Wheels è un tipo di riferimento.

Se hai il seguente

public class Car
{
   public int ID;
}

E tu provi a chiamare questo

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

Otterrai la seguente eccezione

InvalidCastException: impossibile eseguire il cast dell'oggetto di tipo 'System.Linq.Expressions.UnaryExpression' per digitare 'System.Linq.Expressions.MemberExpression'.

Penso che questo abbia a che fare con il fatto che stai passando un tipo di valore all'espressione, quindi deve essere racchiuso in un oggetto. Se si passa un tipo di riferimento, non è necessario inserirlo in un riquadro.

Quello che puoi fare invece è questo:

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


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché