Converta a expressão Linq "obj => obj.Prop" em "parent => parent.obj.Prop"
Eu tenho uma expressão existente do tipoExpression<Func<T, object>>
; contém valores comocust => cust.Name
.
Eu também tenho uma classe pai com um campo do tipoT
. Eu preciso de um método que aceite o acima como parâmetro e gere uma nova expressão que leva a classe pai (TModel
) como um parâmetro. Isso será usado como um parâmetro de expressão de um método MVC.
Portanto,cust => cust.Name
torna-separent => parent.Customer.Name
.
Da mesma forma,cust => cust.Address.State
torna-separent => parent.Customer.Address.State
.
Aqui está minha versão inicial:
//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);
}
O erro que estou recebendo atualmente é quando tenho um campo com várias partes (ou seja,cust.Address.State
em vez de apenascust.Name
) Eu recebo um erro novar member
linha em que o membro especificado não existe - o que é verdadeiro, pois o corpo nesse se refere ao filho do pai (Customer
) e não o item que contém o membro (Address
)
Aqui está o que eu gostaria de poder fazer:
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);
}
Qualquer ajuda para chegar a esse ponto seria muito apreciada.
Editar: foi marcado como uma possível duplicata deessa questão; no entanto, a única semelhança real é a solução (que é, de fato, a mesma). A composição de expressões não é uma solução intuitiva para acessar propriedades aninhadas por meio de expressões (a menos que a intuição de alguém seja guiada por determinada experiência, que não deve ser assumida). Também editei a pergunta para observar que a solução precisa ser adequada para um parâmetro de um método MVC, o que limita as soluções possíveis.