Get PropertyInfo of a parameter passed as lambda expression

I wouldn't use PropertyInfo, just like Reed Copsey said in his answer, but just for information, you can extract the PropertyInfo of an expression with this:

public PropertyInfo GetPropertyFromExpression<T>(Expression<Func<T, object>> GetPropertyLambda)
{
    MemberExpression Exp = null;

    //this line is necessary, because sometimes the expression comes in as Convert(originalexpression)
    if (GetPropertyLambda.Body is UnaryExpression)
    {
        var UnExp = (UnaryExpression)GetPropertyLambda.Body;
        if (UnExp.Operand is MemberExpression)
        {
            Exp = (MemberExpression)UnExp.Operand;
        }
        else
            throw new ArgumentException();
    }
    else if (GetPropertyLambda.Body is MemberExpression)
    {
        Exp = (MemberExpression)GetPropertyLambda.Body;
    }
    else
    {
        throw new ArgumentException();
    }

    return (PropertyInfo)Exp.Member;
}

In the case of a composite expression like MyPerson.PersonData.PersonID, you could go getting the sub expressions until they're not MemberExpressions anymore.

public PropertyInfo GetPropertyFromExpression<T>(Expression<Func<T, object>> GetPropertyLambda)
{
    //same body of above method without the return line.
    //....
    //....
    //....

    var Result = (PropertyInfo)Exp.Member;

    var Sub = Exp.Expression;

    while (Sub is MemberExpression)
    {
        Exp = (MemberExpression)Sub;
        Result = (PropertyInfo)Exp.Member;
        Sub = Exp.Expression;
    }

    return Result;
    //beware, this will return the last property in the expression.
    //when using GetValue and SetValue, the object needed will not be
    //the first object in the expression, but the one prior to the last.
    //To use those methods with the first object, you will need to keep
    //track of all properties in all member expressions above and do
    //some recursive Get/Set following the sequence of the expression.
}

This is possible, and there's no need to use PropertyInfo.

You'd design your method like so:

public bool Update<T>(int id, Action<T> updateMethod)
    // where T  : SomeDbEntityType
{
    T entity = LoadFromDatabase(id); // Load your "person" or whatever

    if (entity == null) 
        return false; // If you want to support fails this way, etc...

    // Calls the method on the person
    updateMethod(entity);

    SaveEntity(entity); // Do whatever you need to persist the values

    return true;
}

Tags:

C#

.Net