Given an Expression<Func<TEntity, bool>> along the lines of
entity => entity.SubEntity.Any(
subEntity => (
(subEntity.SomeProperty == False)
AndAlso
subEntity.SubSubEntity.FooProperty.StartsWith(
value(SomeClass+<>c__DisplayClass0).ComparisonProperty
)
AndAlso
subEntity.SubSubEntity.BarProperty == "Bar"
AndAlso
subEntity.SubSubEntity.SubSubSubEntity.Any(
subSubSubEntity => (x.SubSubSubSubEntity.BazProperty == "whatever")
)
)
)
I am trying to extract a list property conditions by type, i.e.
TEntity : [ /* no conditions for immediate members of TEntity */ ]
TSubEntity : [ { SomeProperty == False } ]
TSubSubEntity : [ { FooProperty.StartsWith(/* ... */) },
{ BarProperty == "Bar" } ],
TSubSubSubEntity : [ /* no conditions for immediate members of TSubSubSubEntity */ ],
TSubSubSubSubEntity : [ { BazProperty == "whatever" } ]
So far, I have created an ExpressionVisitor and identified the VisitBinary method as the one I want to plug into in order to obtain my information.
I am still at a loss about
- how to determine whether the
BinaryExpressionI am looking at represents a terminal statement (in the sense that there are no more nested expressions that I need to look at) - how to determine the Entity type that the
BinaryExpressionis concerned with - whether I need to override any of the other
ExpressionVisitormethods to cover for cases that I have not considered yet.
Not sure what really is the use case, but here is some starting point
The idea is simple. Override
Visitmethod just to maintain a stack of processing expressions. The main processing is inside theVisitMemberoverride, which is called for each property/field accessor. Thenode.Expression.NodeType != ExpressionType.Constantis used to eliminate the closure members, while the second condition eliminates collection properties. Finally, the potential condition expression is extracted from the stack.The result is including both
MemberExpressionand theExpressionwhere it is used.MemberExpression.Expression.Typeis your entity type,MemberExpression.Memberis the property/field of that type.Sample test: