obj.Prop"转换为 "parent => parent.obj.Prop"-6ren"> obj.Prop"转换为 "parent => parent.obj.Prop"-我有一个类型为 Expression> 的现有表达式;它包含类似 cust => cust.Name 的值. 我还有一个父类,其字段类型为 T .我需要一个接受上述作为参数并生成一个以父类 ( TMo-6ren">
gpt4 book ai didi

c# - 将 Linq 表达式 "obj => obj.Prop"转换为 "parent => parent.obj.Prop"

转载 作者:行者123 更新时间:2023-11-30 12:56:37 26 4
gpt4 key购买 nike

我有一个类型为 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 member 上收到错误消息指定成员不存在的行 - 这是正确的,因为正文指的是父项的子项 ( Customer ) 而不是包含该成员的项目 ( Address )。

这是我希望我能做的:

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

对于达到这一点的任何帮助,我们将不胜感激。

编辑:这被标记为可能与 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);

关于c# - 将 Linq 表达式 "obj => obj.Prop"转换为 "parent => parent.obj.Prop",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40271118/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com