c# - How should I share filtering logic between multiple LINQ-where clauses? -


let a class whith property hello. filter collections of a instances property in many places. i'd make somewhere static member of type expression<func<a, bool>> denotes filtering predicate , use in places filtering. (this predicate transformed orm concrete db-specific expression.)

next. there exists class b property of type a. filter collection of b instances same logic used in first case (by property hello of class a).

question. correct way implement , reduce code duplication?

my suggestion. add 3 things: 1) interface iwitha property of type a, 2) class witha<t> implementing interface iwitha , providing property of type t, 3) static property of type expression<func<iwitha, bool>> implementing filtering logic. demo code following.

    public static void main() {         var listofas = new list<a>().asqueryable();         var query0 = listofas             .select(a => new witha<a> {                 = a,                 smth = a,             })             .where(filter);         var listofbs = new list<b>().asqueryable();         var query1 = listofbs             .select(b => new witha<b> {                 = b.a,                 smth = b,             })             .where(filter);     }      private class {         public int hello { get; set; }     }      private class b {         public a { get; set; }     }      private interface iwitha {         a { get; set; }     }      private class witha<t> : iwitha {         public a { get; set; }         public t smth { get; set; }     }      private static readonly expression<func<iwitha, bool>> filter = => a.a.hello > 0; 

the problem approach: 1) 1 must make select(x => new witha<x> { ... }), 2) orm may not support this.

about answer. satisfied accepted answer (by ivan stoev). think best possible approach. helpful @ suggestion mihail stancescu (see in comments question). still not understand answer user853710; may useful also.

i create , use helper function converts original expression<a, bool> expression<b, bool> using system.linq.expressions this

public static class expressionutils {     public static expression<func<ttarget, bool>> convertto<tsource, ttarget>(this expression<func<tsource, bool>> source, expression<func<ttarget, tsource>> sourceselector)     {         var body = new parameterexpressionreplacer { source = source.parameters[0], target = sourceselector.body }.visit(source.body);         var lambda = expression.lambda<func<ttarget, bool>>(body, sourceselector.parameters);         return lambda;     }      class parameterexpressionreplacer : expressionvisitor     {         public parameterexpression source;         public expression target;         protected override expression visitparameter(parameterexpression node)         {             return node == source ? target : base.visitparameter(node);         }     } } 

sample usage

expression<func<a, bool>> filtera = item => item.hello == 2; // original logic var filterb = filtera.convertto((b b) => b.a); 

this approach doesn't require changes entity model. of course can cache filters in static properties of respective classes if wish, principle still write logic in 1 place , use convert in other places.


Comments

Popular posts from this blog

sql - VB.NET Operand type clash: date is incompatible with int error -

SVG stroke-linecap doesn't work for circles in Firefox? -

python - TypeError: Scalar value for argument 'color' is not numeric in openCV -