Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “转换Linq表达式”;obj=>;“目标道具”;变成;父项=>;“父对象属性”;_C#_Asp.net Mvc_Linq_Linq Expressions - Fatal编程技术网

C# “转换Linq表达式”;obj=>;“目标道具”;变成;父项=>;“父对象属性”;

C# “转换Linq表达式”;obj=>;“目标道具”;变成;父项=>;“父对象属性”;,c#,asp.net-mvc,linq,linq-expressions,C#,Asp.net Mvc,Linq,Linq Expressions,我有一个类型为expression的现有表达式;它包含的值类似于cust=>cust.Name 我还有一个父类,其字段类型为T。我需要一个方法,该方法接受上述内容作为参数,并生成一个以父类(TModel)为参数的新表达式。这将用作MVC方法的表达式参数 因此,cust=>cust.Name变成了parent=>parent.Customer.Name 同样地,cust=>cust.Address.State变为parent=>parent.Customer.Address.State 以下是我的

我有一个类型为
expression
的现有表达式;它包含的值类似于
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);
    }
如果您能帮助我们做到这一点,我们将不胜感激


编辑:这被标记为的可能副本;然而,唯一真正相似的是解决方案(事实上是相同的)。编写表达式并不是通过表达式访问嵌套属性的直观解决方案(除非用户的使用受到某些经验的指导,而这些经验不应被假定)。我还编辑了这个问题,以注意解决方案需要适合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]);
}
现在,您可以使用表达式选择属性:

Expression<Func<Customer, object>> propertySelector = cust => cust.Name;
expressionpropertyselector=cust=>cust.Name;
以及从模型中选择该对象的表达式:

Expression<Func<CustomerModel, Customer>> modelSelector = model => model.Customer;
expressionmodelselector=model=>model.Customer;
并组成:

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

expression为什么不能从父对象的子对象属性调用这些表达式,而不是使它们变异以直接在父对象上工作?使用
parent=>(cust=>cust.Name)(parent.Customer)
会简单得多。@TravisJ,我正在使用所有这些来连接基类,因此,事先知道的细节很少。也许有更好的方法来做我正在做的事情,但这种方法会起作用。@poke,我不知道那有什么用。您是否将客户视为一种表情?你能对未知的表达式做同样的事情吗(我不知道
家长
客户
的类型,也不知道
姓名
的字段或类型。很酷,可能是神圣垃圾的重复。我能够快速实现这一点,但我想花更多的时间来弄清楚它到底是如何工作的。我还对你的答案进行了一些快速编辑;中间w因为一次又一次的参数类型拼写错误。您还需要在visit方法中返回到

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