private static Expression BuildNavigationExpression(Expression parameter, OperatorComparer comparer, object value, params string[] properties)
        {
            Expression resultExpression;
            Type       childType = null;

            if (properties.Count() > 1)
            {
                //build path
                parameter = Expression.Property(parameter, properties[0]);
                var isCollection = typeof(IEnumerable).IsAssignableFrom(parameter.Type);
                //if it´s a collection we later need to use the predicate in the methodexpressioncall
                Expression childParameter;
                if (isCollection)
                {
                    childType      = parameter.Type.GetGenericArguments()[0];
                    childParameter = Expression.Parameter(childType, childType.Name);
                }
                else
                {
                    childParameter = parameter;
                }
                //skip current property and get navigation property expression recursivly
                var innerProperties = properties.Skip(1).ToArray();
                var predicate       = BuildNavigationExpression(childParameter, comparer, value, innerProperties);
                resultExpression = isCollection ? BuildSubQuery(parameter, childType, predicate) : predicate;
            }
            else
            {
                //build final predicate
                resultExpression = BuildCondition(parameter, properties[0], comparer, value);
            }
            return(resultExpression);
        }
예제 #2
0
        public void TypesWithoutOperators_Throw()
        {
            var subject = new OperatorComparer <ComparisonSubject>();

            Assert.That(() => subject.Compare(ComparisonSubject.One, ComparisonSubject.Two),
                        Throws.InstanceOf <InvalidOperationException>());
        }
        private Expression BuildComparsion(Expression left, OperatorComparer comparer, Expression right)
        {
            var mask = new List <OperatorComparer> {
                OperatorComparer.Contains,
                OperatorComparer.NotContains,
                OperatorComparer.StartsWith,
                OperatorComparer.NotStartsWith,
                OperatorComparer.EndsWith,
                OperatorComparer.NotEndsWith
            };

            var rangeMask = new List <OperatorComparer>
            {
                OperatorComparer.BetweenExclusive,
                OperatorComparer.BetweenInclusive,
                OperatorComparer.BetweenHigherInclusive,
                OperatorComparer.BetweenLowerInclusive
            };

            if (mask.Contains(comparer) && left.Type != typeof(string))
            {
                comparer = OperatorComparer.Equals;
            }

            if (rangeMask.Contains(comparer))
            {
            }
            else if (!mask.Contains(comparer))
            {
                return(Expression.MakeBinary((ExpressionType)comparer, left, Expression.Convert(right, left.Type)));
            }

            return(BuildStringCondition(left, comparer, right));
        }
        private Expression BuildStringCondition(Expression left, OperatorComparer comparer, Expression right)
        {
            var isNot        = false;
            var operatorName = Enum.GetName(typeof(OperatorComparer), comparer);

            if (operatorName.Contains("Not"))
            {
                isNot        = true;
                operatorName = operatorName.Replace("Not", "");
            }

            // Single or first, we'll need to debug
            var compareMethod = typeof(string).GetMethods()
                                .Single(m => m.GetParameters().Any(p => p.ParameterType == typeof(string)) &&
                                        m.Name.Equals(operatorName) && m.GetParameters().Count() == 1);
            //we assume ignoreCase, so call ToLower on paramter and memberexpression
            var toLowerMethod = typeof(string).GetMethods()
                                .Single(m => m.Name.Equals("ToLower") && m.GetParameters().Count() == 0);

            left  = Expression.Call(Expression.Coalesce(left, Expression.Constant(string.Empty)), toLowerMethod);
            right = Expression.Call(right, toLowerMethod);

            if (isNot)
            {
                return(Expression.Not(Expression.Call(left, compareMethod, right)));
            }
            else
            {
                return(Expression.Call(left, compareMethod, right));
            }
        }
예제 #5
0
        public static Expression <Func <T, bool> > BuildPredicate <T>(object value, OperatorComparer comparer,
                                                                      params string[] properties)
        {
            var parameterExpression = Expression.Parameter(typeof(T), typeof(T).Name);

            return((Expression <Func <T, bool> >)BuildNavigationExpression(parameterExpression, comparer, value,
                                                                           properties));
        }
예제 #6
0
        public void Explore()
        {
            IComparer <OperatorsOnly> subject = new OperatorComparer <OperatorsOnly>(Direction.Descending);

            Assert.That(subject.Compare(new OperatorsOnly(1), new OperatorsOnly(2)), Is.GreaterThan(0));
            Assert.That(subject.Compare(new OperatorsOnly(2), new OperatorsOnly(1)), Is.LessThan(0));
            Assert.That(subject.Compare(new OperatorsOnly(2), new OperatorsOnly(2)), Is.EqualTo(0));
        }
 private static Expression BuildStringCondition(Expression left, OperatorComparer comparer, Expression right)
 {
     var compareMethod = typeof(string).GetMethods().Single(m => m.Name.Equals(Enum.GetName(typeof(OperatorComparer), comparer)) && m.GetParameters().Count() == 1);
     //we assume ignoreCase, so call ToLower on paramter and memberexpression
     var toLowerMethod = typeof(string).GetMethods().Single(m => m.Name.Equals("ToLower") && m.GetParameters().Count() == 0);
     left = Expression.Call(left, toLowerMethod);
     right = Expression.Call(right, toLowerMethod);
     return Expression.Call(left, compareMethod, right);
 } 
예제 #8
0
        public void Compare_HonorsDirection()
        {
            var subject = new OperatorComparer <OperatorsOnly>();

            Assert.That(subject.Compare(new OperatorsOnly(1), new OperatorsOnly(2)), Is.LessThan(0));
            Assert.That(subject.Compare(new OperatorsOnly(2), new OperatorsOnly(1)), Is.GreaterThan(0));
            Assert.That(subject.Compare(new OperatorsOnly(2), new OperatorsOnly(2)), Is.EqualTo(0));

            subject = new OperatorComparer <OperatorsOnly>(Direction.Descending);
            Assert.That(subject.Compare(new OperatorsOnly(1), new OperatorsOnly(2)), Is.GreaterThan(0));
            Assert.That(subject.Compare(new OperatorsOnly(2), new OperatorsOnly(1)), Is.LessThan(0));
            Assert.That(subject.Compare(new OperatorsOnly(2), new OperatorsOnly(2)), Is.EqualTo(0));
        }
 private static Expression BuildComparsion(Expression left, OperatorComparer comparer, Expression right)
 {
     var mask = new List<OperatorComparer>{
         OperatorComparer.Contains,
         OperatorComparer.StartsWith,
         OperatorComparer.EndsWith
     };
     if(mask.Contains(comparer) && left.Type != typeof(string))
     {
         comparer = OperatorComparer.Equals;
     }
     if(!mask.Contains(comparer))
     {
         return Expression.MakeBinary((ExpressionType)comparer, left, Expression.Convert(right,left.Type));
     }
     return BuildStringCondition(left, comparer, right);            
 }
        /// <summary>
        /// Used to build Expression for the specifications
        /// </summary>
        /// <typeparam name="T"> The Type </typeparam>
        /// <param name="name"> (the name of the colomn to be filtered)</param>
        /// <param name="value">(the value to be used for the comparision)</param>
        /// <param name="comparer">type of comparer (Equal,Contains, NotEqual)</param>
        /// <returns></returns>
        public static Expression <Func <T, bool> > BuildPredicate <T>(string name, string value, OperatorComparer comparer)
        {
            if (typeof(T).GetProperties().Any(t => t.Name == name))
            {
                Expression <Func <T, bool> > predicateCompiled =
                    ExpressionBuilder.BuildPredicate <T>(value, comparer, name);

                return(predicateCompiled);
            }
            else
            {
                throw new Exception("Property Not Found, Please check property name used");
            }
        }
예제 #11
0
        /// <summary>
        /// Build Search Condition
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="property"></param>
        /// <param name="comparer"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static Expression BuildCondition(Expression parameter, string property, OperatorComparer comparer, object value)
        {
            Expression       predicate = null;
            MemberExpression left      = null;

            var childProperty = parameter.Type.GetProperty(property);

            if (childProperty == null)
            {
                if (property.Split('.').Count() > 1)
                {
                    var splitPropertyName = property.Split('.');

                    MemberExpression selector    = null;
                    Expression       propertyExp = parameter;
                    foreach (var x in splitPropertyName)
                    {
                        selector    = Expression.Property(propertyExp, x.Split(' ')[0]);
                        propertyExp = selector;
                    }
                    left = selector;
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                left = Expression.Property(parameter, childProperty);
            }



            var right = Expression.Constant(value);

            bool isNumericSearch = long.TryParse(value.ToString(), out long testNumeric);

            var isNumericField = new string[] { "Int64", "Int32", "Int16", "Byte" }.Contains(left.Type.Name);

            //if it is numeric, ignore operator, always set to equals, other operator are not performance wise with numeric
            if (isNumericSearch && isNumericField)
            {
                if (left.Type.Name.Equals("Int64"))
                {
                    right = Expression.Constant(Convert.ToInt64(value));
                }
                else if (left.Type.Name.Equals("Int32"))
                {
                    right = Expression.Constant(Convert.ToInt32(value));
                }
                else if (left.Type.Name.Equals("Int16") || left.Type.Name.Equals("Byte"))
                {
                    right = Expression.Constant(Convert.ToInt16(value));
                }
                if (comparer == OperatorComparer.Contains)
                {
                    predicate = Expression.MakeBinary((ExpressionType)OperatorComparer.Equals, left, right);
                }
                else
                {
                    predicate = Expression.MakeBinary((ExpressionType)comparer, left, right);
                }
            }

            else if (!isNumericSearch && isNumericField)
            {
                //Skip building comparison for numeric field when the search string is not numeric
                return(null);
            }
            else if (isNumericSearch && !isNumericField)
            {
                // Sometimes the field is not detected as numeric but data is a numeric type
                right     = Expression.Constant(Convert.ToString(value));
                predicate = BuildComparsion(left, comparer, right);
            }
            else
            {
                if (left.Type.Name.Equals("DateTime"))
                {
                    return(null);
                }
                predicate = BuildComparsion(left, comparer, right);
            }

            return(MakeLambda(parameter, predicate));
        }
예제 #12
0
        /// <summary>
        /// Build Search Predicate for property
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value">Search Value </param>
        /// <param name="comparer">Comparision Operator </param>
        /// <param name="property">Property Name </param>
        /// <returns></returns>
        public static Expression <Func <T, bool> > BuildPredicate <T>(object value, OperatorComparer comparer, string property)
        {
            var parameterExpression = Expression.Parameter(typeof(T), typeof(T).Name);

            return((Expression <Func <T, bool> >)BuildCondition(parameterExpression, property, comparer, value));
        }
 private static Expression BuildCondition(Expression parameter, string property, OperatorComparer comparer, object value)
 {
     var childProperty = parameter.Type.GetProperty(property);
     var left = Expression.Property(parameter, childProperty);
     var right = Expression.Constant(value);
     var predicate = BuildComparsion(left, comparer, right);
     return MakeLambda(parameter, predicate);
 }
예제 #14
0
        private static Expression <Func <T, bool> > BuildCondition <T>(Expression parameter, string property, OperatorComparer comparer, object value)
        {
            var childProperty = parameter.Type.GetProperty(property);
            var left          = Expression.Property(parameter, childProperty);
            var right         = Expression.Constant(value.TryCast(left.Type));
            var predicate     = BuildComparsion(left, comparer, right);

            return(MakeLambda <T>(parameter, predicate));
        }
예제 #15
0
        public void Ctor_SetsDirection()
        {
            var subject = new OperatorComparer <OperatorsOnly>(Direction.Descending);

            Assert.That(subject.SortDirection, Is.EqualTo(Direction.Descending));
        }
예제 #16
0
        public void Ctor_DefaultsToAscending()
        {
            var subject = new OperatorComparer <OperatorsOnly>();

            Assert.That(subject.SortDirection, Is.EqualTo(Direction.Ascending));
        }
예제 #17
0
 public int Compare(string x, string y)
 {
     return(OperatorComparer.SCompare(x, y));
 }