Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically evaluating a property string with Expressions

Tags:

c#

lambda

How do I build an expression that will fulfill the following goal:

public object Eval(object rootObj, string propertyString)

eg: Eval(person, "Address.ZipCode") => return person.Address.ZipCode

Expression.PropertyOrField doesn't work because I don't have the type of each intermediate property. I'd like to avoid creating a dependency on a scripting library.

I want to try to use expressions because it would allow me to store a cache of these expression trees as they would be executed several times. I'm aware that it's possible to do this iteratively or recursively with reflection.

like image 217
Kir Avatar asked May 14 '13 13:05

Kir


2 Answers

It sounds like you're looking for something like this:

public object Eval(object root, string propertyString)
{
    var propertyNames = propertyString.Split('.');
    foreach(var prop in propertyNames)
    {
        var property = root.GetType().GetProperty(prop);
        if (property == null)
        {
            throw new Exception(...);
        }

        root = property.GetValue(root, null);
    }

    return root;
}

To create an Expression use this:

public Expression Eval(object root, string propertyString)
{
    var propertyNames = propertyString.Split('.');
    ParameterExpression param = Expression.Parameter(root.GetType, "_");
    Expression property = param;
    foreach(var prop in propertyName)
    {
        property = Expression.PropertyOrField(property, prop);
    }

    return Expression.Lambda(property, param);
}
like image 90
p.s.w.g Avatar answered Jan 01 '23 07:01

p.s.w.g


Here's a recursive version of p.s.w.g's code, working with Expressions.

public Expression Eval(Expression expression, string property)
{
    var split = property.Split('.');
    if (split.Length == 1)
    {
        return Expression.PropertyOrField(expression, property);
    }
    else
    {
        return Eval(Expression.PropertyOrField(expression, split[0]), property.Replace(split[0] + ".", ""));
    }
}
like image 29
Bobson Avatar answered Jan 01 '23 09:01

Bobson