obj.Prop" to "parent => parent.obj.Prop" I have an existing type expression Expression>; it co...">

Convert Linq expression "obj => obj.Prop" to "parent => parent.obj.Prop"

I have an existing type expression Expression<Func<T, object>>; it contains values ​​such as cust => cust.Name.

I also have a parent class with a type field T. I need a method that takes the above as a parameter and generates a new expression that takes the parent class ( TModel) as a parameter. This will be used as an expression parameter for the MVC method.

So it cust => cust.Namebecomes parent => parent.Customer.Name.

Similarly, cust => cust.Address.Stateit becomes parent => parent.Customer.Address.State.

Here is my initial version:

    //note: the FieldDefinition object contains the first expression
    //described above, plus the MemberInfo object for the property/field
    //in question
    public Expression<Func<TModel, object>> ExpressionFromField<TModel>(FieldDefinition<T> field)
        where TModel: BaseModel<T>
    {
        var param = Expression.Parameter(typeof(TModel), "t");

        //Note in the next line "nameof(SelectedItem)". This is a reference
        //to the property in TModel that contains the instance from which
        //to retrieve the value. It is unqualified because this method
        //resides within TModel.
        var body = Expression.PropertyOrField(param, nameof(SelectedItem));
        var member = Expression.MakeMemberAccess(body, field.Member);
        return Expression.Lambda<Func<TModel, object>>(member, param);
    }

, , (.. cust.Address.State cust.Name). var member, - , (Customer), , ().

:

    public Expression<Func<TModel, object>> ExpressionFromField<TModel>(FieldDefinition<T> field)
        where TModel: BaseModel<T>
    {
        var param = Expression.Parameter(typeof(TModel), "t");
        var body = Expression.PropertyOrField(param, nameof(SelectedItem));
        var IWantThis = Expression.ApplyExpressionToField(field.Expression, body);
        return Expression.Lambda<Func<TModel, object>>(IWantThis, param);
    }

, , .

: ; - (, , ). ( , ). , , MVC, .

+4
1

, , , :

public static Expression<Func<T, TResult>> Compose<T, TIntermediate, TResult>(
    this Expression<Func<T, TIntermediate>> first,
    Expression<Func<TIntermediate, TResult>> second)
{
    return Expression.Lambda<Func<T, TResult>>(
        second.Body.Replace(second.Parameters[0], first.Body),
        first.Parameters[0]);
}

, :

public class ReplaceVisitor:ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }

    public override Expression Visit(Expression ex)
    {
        if(ex == from) return to;
        else return base.Visit(ex);
    }  
}

public static Expression Replace(this Expression ex,
    Expression from,
    Expression to)
{
    return new ReplaceVisitor(from, to).Visit(ex);
}

, :

Expression<Func<Customer, object>> propertySelector = cust => cust.Name;

, :

Expression<Func<CustomerModel, Customer>> modelSelector = model => model.Customer;

:

Expression<Func<Customer, object> magic = modelSelector.Compose(propertySelector);
+5

All Articles