private void PredicateBuilderByExpressions(
            IDictionary <PropertyInfo, SearchPredicatePropertyInfo> propertyInfoByPropName)
        {
            foreach (var(prop, searchPredicatePropertyInfo) in propertyInfoByPropName)
            {
                PropertyOrField     = searchPredicatePropertyInfo.PropertyOrField;
                EntityName          = searchPredicatePropertyInfo.EntityName;
                FilterPropertyValue = searchPredicatePropertyInfo.PropertyValue;
                FilterPropertyType  = prop.PropertyType;
                EntityPropertyType  = searchPredicatePropertyInfo.InstanceTypeOfProperty
                                      .GetProperty(EntityName.ToUpper())?.PropertyType;
                var predicateBitwiseOperation = searchPredicatePropertyInfo.PredicateBitwiseOperation;

                if (FilterPropertyValue is string _)
                {
                    var expression = StringContainsExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue is StringFilter stringFilter)
                {
                    var expression = StringFilterContainsExpr(stringFilter);


                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue is DateTimeFromToFilter dateTimeFromToFilter)
                {
                    var expression = DateTimeExpr(dateTimeFromToFilter, Item);

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue.GetType().IsGenericType&&
                         FilterPropertyValue.GetType().GetGenericTypeDefinition() == typeof(NumericFilter <>))
                {
                    var expression = NumericFilterExpr(Item);

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (!searchPredicatePropertyInfo.IsEntityTypeProperty)
                {
                    var expression = CollectionContainsExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }

                else
                {
                    var expression = DefaultExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
            }
        }
        private Expression <Func <TEntity, bool> > StringContainsExpr()
        {
            var equalsMethodInfo =
                typeof(string).GetMethod(StringSearchOption.Equals.ToString(),
                                         new[] { typeof(string) });
            var valueToEquals = Expression.Constant(FilterPropertyValue.ToString().ToLower());

            var call = Expression.Call(PropertyOrField, "ToLower", null);
            var methodCallExpression = Expression.Call(call, equalsMethodInfo, valueToEquals);
            var lambda = methodCallExpression.LambdaExpressionBuilder <TEntity>(Item);

            return(lambda);
        }
        private Expression <Func <TEntity, bool> > NumericFilterExpr(ParameterExpression item)
        {
            #region NumericFilter

            var numericFilter = FilterPropertyValue.GetType().GetProperties();
            var value1        = numericFilter[0].GetValue(FilterPropertyValue);
            var value2        = numericFilter[1].GetValue(FilterPropertyValue);
//            var bitOperation = (BitwiseOperation) numericFilter[2].GetValue(FilterPropertyValue);

            #endregion


            #region NumericValue

            var numericValues1 = value1.GetType().GetProperties();
            var numericValue1  = numericValues1[0].GetValue(value1);
            var exprTypeValue1 = (CompareExpressionType)numericValues1[1].GetValue(value1);

            #endregion

            var value1ExprConst = Expression.Constant(numericValue1);

            var expr1 = Expression.MakeBinary(exprTypeValue1.ConvertByName <ExpressionType>(),
                                              PropertyOrField,
                                              value1ExprConst);

            BinaryExpression expr2 = null;
            if (value2 != null)
            {
                #region NumericValue

                var numericValues2 = value2.GetType().GetProperties();
                var numericValue2  = numericValues2[0].GetValue(value2);
                var exprTypeValue2 =
                    (CompareExpressionType)numericValues2[1].GetValue(value2);

                #endregion

                var value2ExprConst = Expression.Constant(numericValue2);
                expr2 = Expression.MakeBinary(exprTypeValue2.ConvertByName <ExpressionType>(),
                                              PropertyOrField,
                                              value2ExprConst);
            }

            var lambda = expr1.LambdaExpressionBuilder <TEntity>(item, expr2, BitwiseOperationExpressions.Or);
            return(lambda);
        }
        private Expression <Func <TEntity, bool> > DefaultExpr()
        {
            var right = Expression.Constant(FilterPropertyValue);
            BinaryExpression binaryExpression;

            if (EntityPropertyType.IsNullable())
            {
                var leftUnaryExpression = Expression.Convert(PropertyOrField, FilterPropertyValue.GetType());

                binaryExpression = Expression.Equal(leftUnaryExpression, right);
            }
            else
            {
                binaryExpression = Expression.Equal(PropertyOrField, right);
            }

            var lambda = binaryExpression.LambdaExpressionBuilder <TEntity>(Item);

            return(lambda);
        }
        private void PredicateBuilderByExpressions(
            IDictionary <PropertyInfo, SearchPredicatePropertyInfo> propertyInfoByPropName)
        {
            foreach (var(prop, searchPredicatePropertyInfo) in propertyInfoByPropName)
            {
                PropertyOrField     = searchPredicatePropertyInfo.PropertyOrField;
                EntityName          = searchPredicatePropertyInfo.EntityName;
                FilterPropertyValue = searchPredicatePropertyInfo.PropertyValue;
                FilterPropertyType  = prop.PropertyType;
                EntityPropertyType  = searchPredicatePropertyInfo.InstanceTypeOfProperty
                                      .GetProperty(EntityName.ToUpper(),
                                                   BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance)?.PropertyType;
                var predicateBitwiseOperation = searchPredicatePropertyInfo.PredicateBitwiseOperation;

                if (FilterPropertyValue is string _)
                {
                    var expression = StringContainsExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue is StringFilter stringFilter)
                {
                    var expression = StringFilterContainsExpr(stringFilter);


                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue is DateTimeFromToFilterComplex dateTimeFromToFilterComplex)
                {
                    if (dateTimeFromToFilterComplex.DateFrom != null && !dateTimeFromToFilterComplex.DateFrom.DateTime.HasValue)
                    {
                        throw new ArgumentNullException(nameof(dateTimeFromToFilterComplex.DateFrom));
                    }

                    var expression = DateTimeExpr(dateTimeFromToFilterComplex, Item);

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue is DateTimeFromToFilter dateTimeFromToFilter)
                {
                    if (!dateTimeFromToFilter.DateFrom.HasValue)
                    {
                        throw new ArgumentNullException(nameof(dateTimeFromToFilter.DateFrom));
                    }

                    var expression = DateTimeExpr(dateTimeFromToFilter, Item);

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (FilterPropertyValue.GetType().IsGenericType&&
                         FilterPropertyValue.GetType().GetGenericTypeDefinition() == typeof(NumericFilter <>))
                {
                    var expression = NumericFilterExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
                else if (!searchPredicatePropertyInfo.IsEntityTypeProperty)
                {
                    var expression = CollectionContainsExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }

                else
                {
                    var expression = DefaultExpr();

                    AutoPredicate.PredicateByOperationType(predicateBitwiseOperation, expression);
                }
            }
        }