Bad Dub
Bad Dub

Reputation: 1593

Access Property Using Reflection C#

I have came up with a function that orders a list by a specified value and then returns a new object value. Where I am stuck is in the .Select statement when trying to get the StatValue. The current example below is what I am trying to do (which obviously doesnt work)

I can get a string value of the passed in order by property, I need to use this property string when getting the StatValue i.e x.GoalsPerGame

private static TodayStatsItem GetStatsValue<TOrderBy>(Expression<Func<PlayerItem, bool>> filter,
    Expression<Func<PlayerItem, TOrderBy>> orderBy, IEnumerable<PlayerItem> items, string desc)
{
    var itemSorted = new TodayStatsItem {
        PlayerItems = items.AsQueryable().OrderBy(orderBy).Select(x => new TodayStatsViewModel
        {
            Name = x.Name,
            //StatValue = ((MemberExpression)orderBy.Body).Member.Name.ToString() // returns GoalsPerGame
            StatValue = x.((MemberExpression)orderBy.Body).Member.Name.ToString() // attempt to access property
        }),
        StatName = desc        
    };
    return itemSorted;
}

The call to this method would looks like this.

this.LeagueItem.Add(GetStatsValue(null, x => x.GoalsPerGame, this.GameReport, "Goals Per Game"));

Is this any way to accomplish this? Thanks.

Upvotes: 1

Views: 1239

Answers (1)

GregorMohorko
GregorMohorko

Reputation: 2877

Here's a method for getting the property value from an object with the specified property name using reflection:

using System.Reflection;

public static object GetPropertyValue(object obj, string propertyName)
{
    PropertyInfo property = obj.GetType().GetProperty(propertyName);
    return property.GetValue(obj);
}

In your case:

string propertyName = ((MemberExpression)orderBy.Body).Member.Name.ToString();
StatValue = (int)GetPropertyValue(x, propertyName); // I'm assuming StatValue is of type int

But to achieve what you are trying to do, you could first compile the orderBy expression and then use it to get the value, which is faster than reflection.

Like this:

private static TodayStatsItem GetStatsValue<TOrderBy>(Expression<Func<PlayerItem, bool>> filter,
Expression<Func<PlayerItem, TOrderBy>> orderBy, IEnumerable<PlayerItem> items, string desc)
{
    Func<PlayerItem, TOrderBy> orderByDeleg = orderBy.Compile();
    var itemSorted = new TodayStatsItem {
    PlayerItems = items.AsQueryable().OrderBy(orderByDeleg).Select(x => new TodayStatsViewModel
        {
            Name = x.Name,
            StatValue = orderByDeleg(x)
        }),
        StatName = desc
    };
    return itemSorted;
}

Upvotes: 2

Related Questions