问题
We have an object and we want to build a linq query based on that object on the fly. This linq statement is equivalent to what we want to build:
Expression<Func<Sample, bool>> linqExpression
= x => x.Child == itemToCompare.Child;
We can't quite come up with the right expression to build the itemToCompare.Child part. Here's what we have so far:
var param = Expression.Parameter(typeof(T), "x");
var key = itemToCompare.GetType().GetProperty("Child");
var rhsConstant = Expression.Constant(item);
var innerLambda = Expression.Lambda<Func<T>>(rhsConstant,
new ParameterExpression[0]);
var rhsMemberAccess = Expression.MakeMemberAccess(innerLambda, key);
body = Expression.Equal(lhsPropertyAccess, rhsMemberAccess);
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
The expression tree for our hand-built query looks like:
Lambda Expression: x => (x.Child = value(SampleTests+Sample))
Expression Body: (x.Child = value(SampleTests+Sample))
Parameter 0: 'x', Type: Sample
NodeType: Lambda
Left Lambda Expression: x.Child
Left NodeType: MemberAccess
Lambda Expression: x
Expression Member: Sample Child
NodeType: Parameter
-- a parameter expression
Right Lambda Expression: value(SampleTests+Sample)
Right NodeType: Constant
NodeType: Constant
Value: SampleTests+Sample
The expression tree for the actual lambda looks like:
Lambda Expression: x => (x.Child = value(SampleTests+<>c__DisplayClass15).itemToCompare.Child)
Expression Body: (x.Child = value(SampleTests+<>c__DisplayClass15).itemToCompare.Child)
Parameter 0: 'x', Type: Sample
NodeType: Lambda
Left Lambda Expression: x.Child
Left NodeType: MemberAccess
Lambda Expression: x
Expression Member: Sample Child
NodeType: Parameter
-- a parameter expression
Right Lambda Expression: value(SampleTests+<>c__DisplayClass15).itemToCompare.Child
Right NodeType: MemberAccess
Lambda Expression: value(SampleTests+<>c__DisplayClass15).itemToCompare
Expression Member: Sample Child
NodeType: MemberAccess
Lambda Expression: value(SampleTests+<>c__DisplayClass15)
Expression Member: Sample itemToCompare
NodeType: Constant
NodeType: Constant
Value: SampleTests+<>c__DisplayClass15
Edit:
We think this works out to
Expression<Func<Sample, bool>> linqExpression
= x => x.Child == (()=>itemToCompare).Child;
which is what we're trying to reproduce in our expression.
Ultimately the goal is to produce an Expression where the Child values are compared using their Type's .Equals() method.
Thanks!
回答1:
You're getting confused by the "inner lambda". There's only one lambda expression:
var param = Expression.Parameter(typeof(Sample), "x");
var key = itemToCompare.GetType().GetProperty("Child");
var rhs = Expression.MakeMemberAccess(Expression.Constant(itemToCompare), key);
var lhs = Expression.MakeMemberAccess(param, key);
var body = Expression.Equal(lhs, rhs);
var lambda = Expression.Lambda<Func<Sample, bool>>(body, param);
来源:https://stackoverflow.com/questions/4001082/manually-build-linq-expression-for-x-x-child-itemtocompare-child