加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 将Linq表达式“obj => obj.Prop”转换为“parent =>

发布时间:2020-12-15 21:02:57 所属栏目:百科 来源:网络整理
导读:我有一个Expression Func T,object类型的现有表达式;它包含像cust =这样的值cust.Name. 我还有一个类型为T的字段的父类.我需要一个接受上述参数的方法,并生成一个以父类(TModel)作为参数的新表达式.这将用作MVC方法的表达式参数. 因此,cust = cust.Name成为p
我有一个Expression< Func< T,object>>类型的现有表达式;它包含像cust =>这样的值cust.Name.

我还有一个类型为T的字段的父类.我需要一个接受上述参数的方法,并生成一个以父类(TModel)作为参数的新表达式.这将用作MVC方法的表达式参数.

因此,cust => cust.Name成为parent => parent.Customer.Name.

同样,cust => cust.Address.State成为parent => parent.Customer.Address.State.

这是我的初始版本:

//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成员行上得到一个指定成员不存在的错误 – 这是真的,因为那里的主体引用了父的子(Customer)而不是包含该成员的项(Address).

这就是我希望我能做到的:

public Expression<Func<TModel,"t");
        var body = Expression.PropertyOrField(param,nameof(SelectedItem));
        var IWantThis = Expression.ApplyExpressionToField(field.Expression,body);
        return Expression.Lambda<Func<TModel,object>>(IWantThis,param);
    }

任何帮助到达这一点将不胜感激.

编辑:这被标记为this question的可能重复;然而,唯一真正的相似之处是解决方案(实际上是相同的).组合表达式不是通过表达式访问嵌套属性的直观解决方案(除非一个人的理解是由某种经验引导的,不应该假设).我还编辑了这个问题,注意解决方案需要适合MVC方法的参数,这限制了可能的解决方案.

解决方法

您正在寻找的是组合表达式的能力,就像您可以组合函数一样:

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);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读