VFein
VFein

Reputation: 1061

Combine the results of two expressions

I want to compose the results of two Linq Expressions. The result I would like composed would be the composition of both return objects.

Expression<Func<Person, User>> basicUser = t => new User() { Name = t.FirstName };
Expression<Func<Person, User>> detailedUser = t => Execute basicUser and add the following  assignments { DOB = t.DOB };

WHERE detailedUser inherits so to speak all of the logic in basicUser and sets the DOB property of the User object.

This would be used like so:

context.CreateObjectSet<Persons>().Where(p => p.PersonType == User).Select<Person, User>(detailedUser); 

Any help would be greatly appreciated.

Upvotes: 2

Views: 189

Answers (1)

Jeff Mercado
Jeff Mercado

Reputation: 134801

You would have to rebuild the expression to add the field.

Assuming these expressions will not be complex and the basicUser expression will always be in that form, you could just alter the expression to add a new binding. You can do that with the help of a simple visitor.

public class AddDobBindingVisitor : ExpressionVisitor
{
    private ParameterExpression parameter;

    protected override Expression VisitLambda<T>(Expression<T> node)
    {
        parameter = node.Parameters.Single();
        return base.VisitLambda(node);
    }

    protected override Expression VisitMemberInit(MemberInitExpression node)
    {
        var member = typeof(User).GetProperty("DOB");
        var newBindings = new[]
        {
            Expression.Bind(member, Expression.Property(parameter, "DOB")),
        };
        var updatedNode = node.Update(
            node.NewExpression,
            node.Bindings.Concat(newBindings));
        return base.VisitMemberInit(updatedNode);
    }
}

Then to apply the changes:

Expression<Func<Person, User>> basicUser = person => new User()
{
    Name = person.FirstName
};
var detailedUser = (Expression<Func<Person, User>>)new AddDobBindingVisitor()
    .Visit(basicUser);
// detailedUser:
//     person => new User()
//     {
//         Name = person.FirstName,
//         DOB = person.DOB
//     }

Upvotes: 2

Related Questions