Is it possible to convert a lambda expression of s

2019-07-28 11:31发布

问题:

public class Entity
{
    public int A { get; set; }
    public string B { get; set; }
}

Expression<Func<Entity,object>> expr = x => x.A;
Expression<Func<Entity,int>> exprAtRuntime = x => x.A;

Expression<Func<Entity,object>> expr2 = x => x.B;
Expression<Func<Entity,string>> expr2AtRuntime = x => x.B;

How can I take expr and convert it to the type of expr2 at runtime?

Likewise, I need to do the same for property B. I need to accept a params array of type Expression<Func<Entity,object>> which represents accessing different properties of an object, so they all need to have the Entity type and the general return type of object (as answered in this precursor question).

But from that expression, I need to construct it's more strongly-typed version for each element of the params array (i.e. convert Expression<Func<TEntity,object>> to a type specific to the underlying property being accessed Expression<Func<TEntity,TProperty>>, using information about the type of the property being accessed on the entity type. How can this be done?

回答1:

To do this, you can use an ExpressionVisitor that removes the Convert (if it exists) and then fixes up the delegate type:

class RemoveConvertVisitor : ExpressionVisitor
{
    protected override Expression VisitUnary(UnaryExpression node) =>
        node.NodeType == ExpressionType.Convert ? node.Operand : base.VisitUnary(node);

    protected override Expression VisitLambda<T>(Expression<T> node) =>
        Expression.Lambda(Visit(node.Body), node.Parameters);
}