184

is there a way to get the value of a property of a object based on its name?

For example if I have:

public class Car : Vehicle
{
   public string Make { get; set; }
}

and

var car = new Car { Make="Ford" };

I want to write a method where I can pass in the property name and it would return the property value. ie:

public string GetPropertyValue(string propertyName)
{
   return the value of the property;
}
Coder 2
  • 4,761
  • 12
  • 40
  • 43

10 Answers10

366
return car.GetType().GetProperty(propertyName).GetValue(car, null);
Matt Greer
  • 60,826
  • 17
  • 123
  • 123
55

You'd have to use reflection

public object GetPropertyValue(object car, string propertyName)
{
   return car.GetType().GetProperties()
      .Single(pi => pi.Name == propertyName)
      .GetValue(car, null);
}

If you want to be really fancy, you could make it an extension method:

public static object GetPropertyValue(this object car, string propertyName)
{
   return car.GetType().GetProperties()
      .Single(pi => pi.Name == propertyName)
      .GetValue(car, null);
}

And then:

string makeValue = (string)car.GetPropertyValue("Make");
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • can I do this also for a SetValue? how? – Piero Alberto May 22 '15 at 09:47
  • 2
    minor thing- extension method probably doesn't need to have the variable named `car` – KyleMit Feb 10 '18 at 23:49
  • To see how to Set the property value, based on a propertyName string, see the answer here: [Setting the value of properties via reflection](https://codereview.stackexchange.com/questions/102289/setting-the-value-of-properties-via-reflection) – nwsmith Aug 01 '19 at 17:32
44

You want Reflection

Type t = typeof(Car);
PropertyInfo prop = t.GetProperty("Make");
if(null != prop)
return prop.GetValue(this, null);
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
11

Expanding on Adam Rackis's answer - we can make the extension method generic simply like this:

public static TResult GetPropertyValue<TResult>(this object t, string propertyName)
{
    object val = t.GetType().GetProperties().Single(pi => pi.Name == propertyName).GetValue(t, null);
    return (TResult)val;
}

You can throw some error handling around that too if you like.

Cameron Forward
  • 702
  • 8
  • 16
8

In addition other guys answer, its Easy to get property value of any object by use Extension method like:

public static class Helper
    {
        public static object GetPropertyValue(this object T, string PropName)
        {
            return T.GetType().GetProperty(PropName) == null ? null : T.GetType().GetProperty(PropName).GetValue(T, null);
        }

    }

Usage is:

Car foo = new Car();
var balbal = foo.GetPropertyValue("Make");
Ali
  • 3,373
  • 5
  • 42
  • 54
7

Simple sample (without write reflection hard code in the client)

class Customer
{
    public string CustomerName { get; set; }
    public string Address { get; set; }
    // approach here
    public string GetPropertyValue(string propertyName)
    {
        try
        {
            return this.GetType().GetProperty(propertyName).GetValue(this, null) as string;
        }
        catch { return null; }
    }
}
//use sample
static void Main(string[] args)
    {
        var customer = new Customer { CustomerName = "Harvey Triana", Address = "Something..." };
        Console.WriteLine(customer.GetPropertyValue("CustomerName"));
    }
Sith2021
  • 3,245
  • 30
  • 22
3

To avoid reflection you could set up a Dictionary with your propery names as keys and functions in the dictionary value part that return the corresponding values from the properties that you request.

Paul McCarthy
  • 818
  • 9
  • 24
1

2 Very short options, 1 with a default value if it fails:

public object GetPropertyValue_WithDefault(
    object _t,
    string _prop,
    object _default = null
)
{
    PropertyInfo pi = _t.GetType().GetProperty(_prop);
    return (pi == null
        ? _default
        : pi.GetValue(_t, null)
    );
}

public object GetPropertyValue(object _t, string _prop)
{
    //because of "?." will return null if property not found
    return _t.GetType().GetProperty(_prop)?.GetValue(_t, null); 
}
Loesil
  • 11
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 01 '23 at 02:05
1

Here is a faster way by creating your own customized RTTI.

public class Car
{
    public string MakeA { get; set; }
    public string MakeB { get; set; }
    public string MakeC { get; set; }

    private readonly Dictionary<string, Func<string>> _stringPropertyMap;
    //For properties of other types, add different typed Dictionary like _stringPropertyMap

    public Car()
    {
        _stringPropertyMap = new Dictionary<string, Func<string>>(3)
        {
            { nameof(MakeA), () => MakeA },
            { nameof(MakeB), () => MakeB },
            { nameof(MakeC), () => MakeC }
        };
    }

    public string GetPropertyValue(string propertyName)
    {
        if (_stringPropertyMap.TryGetValue(propertyName, out var getter))
        {
            return getter();
        }

        throw new InvalidOperationException($"{nameof(Car)} doesn't have a property of name {propertyName}");
    }
}
zwcloud
  • 4,546
  • 3
  • 40
  • 69
  • This only works if all of your properties are strings, which is unlikely. It would need to be generic and return any property. – HackSlash Jul 21 '23 at 17:24
0

Expanding upon the answer given by @zwcloud, we can use any property type if you are using a version of .NET that supports the dynamic type.

Then if you need to dynamically load settings into a property you only have the string name of, you need a separate setter dictionary.

Now we arrive at a solution where we can get or set any property by name. It does take a lot of ceremony to get here but it ends up being much better than reflection.

To make an extension out of this we would need to get into code weaving, where this code could be generated for you at compile time. Tune in next time for another exciting episode of "ain't nobody got time for that".

public class Car
{
    public string MakeA { get; set; }
    public int MakeB { get; set; }
    public decimal MakeC { get; set; }

    private readonly Dictionary<string, Func<dynamic>> _propertyGetterMap;
    
    private readonly Dictionary<string, Action<dynamic>> _propertySetterMap;

    public Car()
    {
        _propertyGetterMap= new Dictionary<string, Func<dynamic>>(3)
        {
            { nameof(MakeA), () => MakeA },
            { nameof(MakeB), () => MakeB },
            { nameof(MakeC), () => MakeC }
        };

        _propertySetterMap= new Dictionary<string, Func<dynamic>>(3)
        {
            { nameof(MakeA), (value) => MakeA = value.ToString() },
            { nameof(MakeB), (value) => MakeB = (int)Convert.ChangeType(value, typeof(int)) },
            { nameof(MakeC), (value) => MakeC = (decimal)Convert.ChangeType(value, typeof(decimal)) }
        };
    }

    public string GetPropertyValue(string propertyName)
    {
        if (_stringPropertyMap.TryGetValue(propertyName, out var getter))
        {
            return getter();
        }

        throw new InvalidOperationException($"{nameof(Car)} doesn't have a property of name {propertyName}");
    }

    public string SetPropertyValue(string propertyName, dynamic value)
    {
        if (_stringPropertyMap.TryGetValue(propertyName, out var setter))
        {
            setter(value);
        }

        throw new InvalidOperationException($"{nameof(Car)} doesn't have a property of name {propertyName}");
    }
}
HackSlash
  • 4,944
  • 2
  • 18
  • 44