mercredi 4 mars 2020

Expression Tree: Get property value of dynamic object

I have list of dynamic objects where I want to query by custom property. In other words, it would look like this if I wasn't going for reflection:

IEnumerable<User> FilterUsers(IEnumerable<User> users, string selectedValue)
{
    users.Where(user => user.Name == selectedValue);
}

So far I've come up with the following implementation that works if users is typed:

IEnumerable<User> FilterUsers(IEnumerable<User> users, string selectedField, string selectedValue)
{
    LabelTarget returnTarget = Expression.Label(typeof(bool));
    ParameterExpression userParameter = Expression.Parameter(typeof(User));
    MemberExpression userSelectedField = Expression.Property(userParameter, selectedField);
    Expression test = Expression.Equal(userSelectedField, Expression.Constant(selectedValue));
    Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
    Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));

    var ex = Expression.Block(
        Expression.IfThenElse(test, iftrue, iffalse),
        Expression.Label(returnTarget, Expression.Constant(false)));

    var whereClause = Expression.Lambda<Func<User, bool>>(
        ex,
        new ParameterExpression[] { userParameter }
    ).Compile();

    return users.Where(user => whereClause(user));
}

What I am really trying to do is to make users dynamic object:

IEnumerable<dynamic> FilterUsers(IEnumerable<dynamic> users, string selectedField, string selectedValue) {
    // ...
    ParameterExpression userParameter = Expression.Parameter(typeof(object)); // ???
    MemberExpression userSelectedField = Expression.Property(userParameter, selectedField); // throws
    // ...
}

This throws the following exception: Instance property 'Name' is not defined for type 'System.Object' (Parameter 'propertyName'). What am I missing?

Alternatively, how can I use Dictionary<string, object>?





Aucun commentaire:

Enregistrer un commentaire