// Make this mess into multiply methods // mistake to introduce classes search and comparator since they're not based on a interface public List <Person> GetPersonsFromRepository(List <Tuple <Search, Comparator> > queries, PersonRepository repo) { var expressionTree = new List <Tuple <Expression, Comparator> >(); // this is the parameter like "person => person.Age = 10" var parameterExpression = Expression.Parameter(typeof(Person), "person"); // Create each expression tree foreach (var query in queries) { var search = query.Item1; // Find parameter first (we already filtered this) var parameterType = typeof(Person).GetProperties() .FirstOrDefault( property => string.Equals(search.Property, property.Name, StringComparison.CurrentCultureIgnoreCase)); // https://msdn.microsoft.com/en-us/library/bb882637(v=vs.110).aspx // Handle left hand (ex. "Name", "Age", "Birthday") Expression left = Expression.Property(parameterExpression, parameterType); Expression right = null; // Handle right hand (ex. 10, "Patrick", '23-11-1993') and parse // person => person.Age == 10 switch (parameterType.Name) { case "Name": right = Expression.Constant(search.Condition, typeof(string)); break; case "Birthday": // TODO: Try and parse this earlier so we don't get an error right = Expression.Constant(DateTime.Parse(search.Condition), typeof(DateTime)); break; case "Age": // TODO: Try and parse this earlier so we don't get an error right = Expression.Constant(int.Parse(search.Condition), typeof(int)); break; } Expression expressionOperator = null; // Handle operators switch (search.Operator) { case '>': expressionOperator = Expression.GreaterThan(left, right); break; case '<': expressionOperator = Expression.LessThan(left, right); break; case '=': expressionOperator = Expression.Equal(left, right); break; } var comparator = query.Item2; expressionTree.Add(new Tuple <Expression, Comparator>(expressionOperator, comparator)); } var expressions = new List <Expression <Func <Person, bool> > >(); // If they're 'all null' then there's only one expression if (expressionTree.All(tree => tree.Item2 == null)) { expressions = expressionTree.Select( expression => Expression.Lambda <Func <Person, bool> >(expression.Item1, parameterExpression)).ToList(); return(repo.GetPersons(expressions.FirstOrDefault().Compile())); } var expressionsTreesCombined = new List <Expression>(); for (int i = 0; i < expressionTree.Count; i++) { var pair = expressionTree[i]; var expression = pair.Item1; var comparator = pair.Item2; // if it's zero, it was the last comparator if (comparator == null) { continue; } if (comparator?.Type == '&') { var nextExpression = expressionTree[i + 1].Item1; expressionsTreesCombined.Add(Expression.And(expression, nextExpression)); } else if (comparator?.Type == '|') { var nextExpression = expressionTree[i + 1].Item1; expressionsTreesCombined.Add(Expression.Or(expression, nextExpression)); } } expressions = expressionsTreesCombined.Select( expression => Expression.Lambda <Func <Person, bool> >(expression, parameterExpression)).ToList(); return(repo.GetPersons(expressions.FirstOrDefault().Compile())); }
public Person GetPersonFromRepository(string searchProperty, char searchOperator, string searchCondition, PersonRepository repo) { var search = new Search(searchProperty, searchOperator, searchCondition); var personTuple = new Tuple <Search, Comparator>(search, null); var personParameter = new List <Tuple <Search, Comparator> >() { personTuple }; return(GetPersonsFromRepository(personParameter, repo).FirstOrDefault()); }