Although the original question was about how to get the value of the property using only a single string as the parameter, it makes a lot of sense here to use an Expression rather than simply a string to ensure that the caller never uses a hard coded property name. Here is a one line version with usage:
public static class Utils ... public static TVal GetPropertyValue<T, TVal>(T t, Expression<Func<T, TVal>> x) => (TVal)((x.Body as MemberExpression)?.Member as PropertyInfo)!.GetValue(t); ... var val = Utils.GetPropertyValue(foo, p => p.Bar);
Here is a slightly better version in terms of readability a error handling:
public static TVal GetPropertyValue<T, TVal>(T t, Expression<Func<T, TVal>> x) { var m = (x.Body as MemberExpression)?.Member; var p = m as PropertyInfo; if (null == p) throw new ArgumentException($"Unknown property: {typeof(T).Name}.{(m?.Name??"???")}"); return (TVal)p.GetValue(t); }
In short you pass in a lambda expression reading a property. The body of the lambda - the part on the right of the fat arrow - is a member expression from which you can get the member name and which you can cast to a PropertyInfo, provided the member is actually a Property and not, for instance, a method.
In the short version, the null forgiving operator - the ! in the expression - tells the compiler that the PropertyInfo will not be null. This is a big lie and you will get a NullReferenceException at runtime. The longer version gives you the name of the property if it manages to get it.
PS: Thanks to Oleg G. for the initial version of this code :)