Search code examples
c#expressionfunc

Get member name that's passed into an Expression


In my ToString() override I'm doing something along the lines of:

public class MyObject
{
    public string Prop1 { get; set; } = "value1";
    public string Prop2 { get; set; } = "value2";

    public override string ToString()
    {
        var parts = new[]
        {
            $"{nameof(Prop1)}={Prop1}",
            $"{nameof(Prop2)}={Prop2}",
        };
        return string.Join(",", parts);
    }
}

Rather than repeating the same "name=value" operation over and over, is it possible to have a function that can work out the name (e.g. Prop1) and the value of that prop?

For example, can I do something like this:

public override string ToString()
{
    var parts = new[]
    {
        GetProp(x => x.Prop1), // returns "Prop1=value1"
        GetProp(x => x.Prop2), // returns "Prop2=value2"
        // ...
    };
    return string.Join(",", parts);
}

I'm thinking I need a function along the lines of this, but I'm not sure of the implementation to get the members name:

private string GetProp(Expression<Func<MyObject, object>> exp)
{
    var name = ""; // <---- How to get the name?
    var value = exp.Compile().Invoke(this);
    return $"{name}={value}";
}

If I inspect exp I can see that the member name is indeed stored under exp.Body.Member.Name, but I cant figure out how to access this.

enter image description here


Solution

  • All you need to do is to cast the body to a MemberExpression like the below :

        private string GetProp(Expression<Func<MyObject, object>> exp)
        {
                var name = ""; // <---- How to get the name?
                if (exp.Body is MemberExpression memberExpression)
                {
                    name = memberExpression.Member.Name;
                }
                else if (exp.Body is UnaryExpression unaryExpression && unaryExpression.Operand is MemberExpression unaryMemberExpression)
                {
                    name = unaryMemberExpression.Member.Name;
                }
    
                var value = exp.Compile().Invoke(this);
                return $"{name}={value}";
        }
    

    Fiddle

    Edit: UnaryExpression checking added.