예제 #1
0
        // 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()));
        }
예제 #2
0
        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());
        }