I have an existing expression of type Expression<Func<T, object>>
; it contains values like cust => cust.Name
.
I also have a parent class with a field of type T
. I need a method that accepts 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 of an MVC method.
Thus, cust => cust.Name
becomes parent => parent.Customer.Name
.
Likewise, cust => cust.Address.State
becomes parent => parent.Customer.Address.State
.
Here's 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);
}
The error I'm currently receiving is when I have a field with multiple parts (i.e. cust.Address.State
instead of just cust.Name
). I get an error on the var member
line that the specified member doesn't exist--which is true, since the body at that refers to the parent's child (Customer
) and not the item that contains the member (Address
).
Here's what I wish I could do:
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);
}
Any help getting to this point would be greatly appreciated.
Edit: This was marked as a possible duplicate of this question; however, the only real similarity is the solution (which is, in fact, the same). Composing expressions is not an intuitive solution to accessing nested properties via expressions (unless one's inuition is guided by certain experience, which should not be assumed). I also edited the question to note that the solution needs to be suitable for a paramter of an MVC method, which limits the possible solutions.