c# - Combine two linq expressions to inject navigation property -
i have identical set of conditions applied 1 class directly or other class having same navigation property.
for example, have home , have agent, agent associated home.
so looking home agency name 'a', or looking agent name 'a', queries follow,
expression<<func<agent,bool>> ax = x=> x.name == "a" ; expression<func<home,bool>> hx = x=> x.agent.name == "a"; i have 100 search queries agent, , have apply them home queryable well. dont mind writing again, difficult maintain know change during course of development.
what want is, want compose expression home query this,
expression<func<home,bool>> hx = combine( x=>x.agent , x=>x.name == "a"); where combine following,
expression<func<t,bool>> combine<t,tnav>( expression<func<t,tnav>> parent, expression<func<tnav,bool>> nav){ // combine above form... (x=>x.agent , x=>x.name == "a") => x => x.agent.name == "a" (x=>x.agent, x=>x.name.startswith("a") || x.name.endswith("a")) => x=>x.agent.name.startswith("a") || x.agent.name.endswith("a") // carefully, x gets replaced x.agent in every node.. // know little expression rewriting, need little }
yes, need visitor replace parts of original expressions. that:
expression<func<t,bool>> combine<t,tnav>(expression<func<t,tnav>> parent, expression<func<tnav,bool>> nav) { var param = expression.parameter(typeof(t), "x"); var visitor = new replacementvisitor(parent.parameters[0], param); var newparentbody = visitor.visit(parent.body); visitor = new replacementvisitor(nav.parameters[0], newparentbody); var body = visitor.visit(nav.body); return expression.lambda<func<t, bool>>(body, param); } public class replacementvisitor : system.linq.expressions.expressionvisitor { private readonly expression _oldexpr; private readonly expression _newexpr; public replacementvisitor(expression oldexpr, expression newexpr) { _oldexpr = oldexpr; _newexpr = newexpr; } public override expression visit(expression node) { if (node == _oldexpr) return _newexpr; return base.visit(node); } } example usage:
expression<func<foo, bar>> expr1 = f => f.bar; expression<func<bar, bool>> expr2 = b => b.baz; var expr = combine(expr1, expr2); // f => f.bar.baz
Comments
Post a Comment