4

For some reasons, I need to create a Dictionary of PropertyInfo instances corresponding to some class' properties (let's call it EntityClass).

Ok, I could use typeof(EntityClass).GetProperties().

But I also need to determine a value for some specific properties (known at compile time). Normally I could do one of the following:

EntityInstance.PropertyX = Value;
typeof(EntityClass).GetProperty("PropertyX").SetValue(EntityInstance, Value, null);

In order to fill up my dictionary, I need to use PropertyInfo instances instead of just setting the values normally. But I don't feel confortable getting properties by their string names. If some EntityClass changes, it would bring many exceptions instead of compile errors. So, what I ask is:

How to get a known property's PropertyInfo without passing the string name? I would love if there's something just like delegates:

SomeDelegateType MyDelegate = EntityInstance.MethodX;

Ideally:

SomePropertyDelegate MyPropertyDelegate = EntityInstance.PropertyX;
Daniel Möller
  • 84,878
  • 18
  • 192
  • 214
  • can you please describe a scenario? I mean, a code before and after modification of Entity. Also, how can you expect the value being passed is of the same type of the property after modification? – Victor Mukherjee May 27 '13 at 16:49
  • possible duplicate of [How to get the PropertyInfo of a specific property?](http://stackoverflow.com/questions/491429/how-to-get-the-propertyinfo-of-a-specific-property) – nawfal Dec 13 '13 at 09:13

2 Answers2

10

Something like this?

string s = GetPropertyName<User>( x=> x.Name );

public string GetPropertyName<T>(Expression<Func<T, object>> lambda)
{
    var member = lambda.Body as MemberExpression;
    var prop = member.Member as PropertyInfo;
    return prop.Name;
}

or

public PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> lambda)
{
    var member = lambda.Body as MemberExpression;
    return member.Member as PropertyInfo;
}

public class User
{
    public string Name { set; get; }
}
I4V
  • 34,891
  • 6
  • 67
  • 79
  • Now what i did just looks like a copy of yours. Similar logic even same User class :) – Mehmet Ataş May 27 '13 at 16:58
  • 2
    `{"Unable to cast object of type 'System.Linq.Expressions.UnaryExpression' to type 'System.Linq.Expressions.MemberExpression'."}` Any hints? – Daniel Möller May 28 '13 at 20:54
  • @Daniel I need more info. class? how do you access the member? – I4V May 28 '13 at 20:57
  • 2
    All right! Some expressions come as a `Convert(original lambda)`, and that's a `UnaryExpression`. But the `Operand` from that `UnaryExpression` is the meant `MemberExpression`. So, just an extra type check and it works!!! Thanks!! – Daniel Möller May 28 '13 at 21:14
  • 1
    I believe the use of `object` instead of the property type in the `Func` is what causes the `Convert` to be added automatically to the expression. Probably the generic version in the other answer would not bring that up. Anyway, both answers fit for what I need. – Daniel Möller May 28 '13 at 21:22
  • Beware of this: http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo ! Not very safe.. – nawfal Dec 13 '13 at 09:44
  • For anyone getting the same error as Daniel, his explanation is correct. If you're trying to follow along with it, here's another [stack overflow question that provides an implemenation](http://stackoverflow.com/a/12420603/1366033) – KyleMit Nov 17 '14 at 16:21
  • Hey, sorry to bring up an old question but I have a doubt. in your example where you are providing `x => x.Name`, how do I get the `object` instance of `x`? Please help me out – Rakshith Ravi Aug 16 '16 at 18:29
4

Not sure what you need but may be it helps you move on.

public class Property<TObj, TProp>
{
    private readonly TObj _instance;
    private readonly PropertyInfo _propInf;

    public Property(TObj o, Expression<Func<TObj, TProp>> expression)
    {
        _propInf = ((PropertyInfo)((MemberExpression)expression.Body).Member);
        _instance = o;
    }

    public TProp Value
    {
        get
        {
            return (TProp)_propInf.GetValue(_instance);
        }
        set
        {
            _propInf.SetValue(_instance, value);
        }
    }
}

public class User
{
    public string Name { get; set; }
}

var user = new User();
var name = new Property<User, string>(user, u => u.Name);
name.Value = "Mehmet";
Console.WriteLine(name.Value == user.Name); // Prints True
Mehmet Ataş
  • 11,081
  • 6
  • 51
  • 78