private static Expression <Func <TDbType, bool> > BuildInnerPredicate <TDbType>(IPredicateParser predicateParser, PropertyInfo searchField, MemberInfo dbFieldMemberInfo)
        {
            var dbType = typeof(TDbType);
            // Create an "x" as TDbType
            var dbTypeParameter = Expression.Parameter(dbType, @"x");
            // Get at x.firstName
            var dbFieldMember = Expression.MakeMemberAccess(dbTypeParameter, dbFieldMemberInfo);
            Expression <Func <TDbType, bool> > predicateInner = null;

            foreach (var predicateItem in predicateParser.Items)
            {
                var predicateItemSingle = predicateItem as PredicateItemSingle;
                var predicateItemRange  = predicateItem as PredicateItemRange;
                if (predicateItemSingle != null)
                {
                    // Create the MethodCallExpression like x.firstName.Contains(criterion)
                    if (searchField.PropertyType == typeof(string))
                    {
                        var str = predicateItemSingle.Value as string ?? "";
                        var startsWithAsterisk = str.StartsWith("*");
                        var endsWithAsterisk   = str.EndsWith("*");
                        str = str.Trim('*').Trim();
                        MethodCallExpression callExpression;
                        if (startsWithAsterisk && !endsWithAsterisk)
                        {
                            callExpression = Expression.Call(dbFieldMember, StringEndsWithMethod, new Expression[] { Expression.Constant(str) });
                        }
                        else if (!startsWithAsterisk && endsWithAsterisk)
                        {
                            callExpression = Expression.Call(dbFieldMember, StringStartsWithMethod, new Expression[] { Expression.Constant(str) });
                        }
                        else
                        {
                            callExpression = Expression.Call(dbFieldMember, StringContainsMethod, new Expression[] { Expression.Constant(str) });
                        }
                        predicateInner = (predicateInner ?? PredicateBuilder.New <TDbType>(false)).Or(Expression.Lambda(callExpression, dbTypeParameter) as Expression <Func <TDbType, bool> >);
                    }
                    else
                    {
                        if (dbFieldMember.Type.IsEnum)
                        {
                            if (!dbFieldMember.Type.IsEnumDefined(predicateItemSingle.Value))
                            {
                                continue;
                            }
                            var enumValue = (int)predicateItemSingle.Value;
                            if (enumValue <= 0)
                            {
                                continue;
                            }
                            var enumObj = Enum.ToObject(dbFieldMember.Type, (int)predicateItemSingle.Value);
                            predicateInner = (predicateInner ?? PredicateBuilder.New <TDbType>(false)).Or(Expression.Lambda <Func <TDbType, bool> >(Expression.Equal(dbFieldMember, Expression.Constant(enumObj)), new[] { dbTypeParameter }));
                        }
                        else
                        {
                            predicateInner = (predicateInner ?? PredicateBuilder.New <TDbType>(false)).Or(Expression.Lambda <Func <TDbType, bool> >(Expression.Equal(dbFieldMember, Expression.Constant(predicateItemSingle.Value)), new[] { dbTypeParameter }));
                        }
                    }
                }
                else if (predicateItemRange != null)
                {
                    var predicateRange = PredicateBuilder.New <TDbType>(true);
                    predicateRange = predicateRange.And(Expression.Lambda <Func <TDbType, bool> >(Expression.GreaterThanOrEqual(dbFieldMember, Expression.Constant(predicateItemRange.Value1)), new[] { dbTypeParameter }));
                    predicateRange = predicateRange.And(Expression.Lambda <Func <TDbType, bool> >(Expression.LessThanOrEqual(dbFieldMember, Expression.Constant(predicateItemRange.Value2)), new[] { dbTypeParameter }));
                    predicateInner = (predicateInner ?? PredicateBuilder.New <TDbType>(false)).Or(predicateRange);
                }
            }
            return(predicateInner);
        }
        //private static readonly MethodInfo BooleanEqualsMethod = typeof(bool).GetMethod(@"Equals", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(bool) }, null);
        /// <summary>
        /// Build a predicate with linq clauses, taking searchCriteria object's properties to define where conditions.
        /// </summary>
        /// <typeparam name="TDbType">Type of entity to build predicate for</typeparam>
        /// <param name="searchCriteria">Object which contains criteria for predicate</param>
        /// <param name="predicateParser">Implementation of predicate parser that will parse predicates as string</param>
        /// <param name="includeNullValues">Determines whether null values are included when constructing query</param>
        /// <returns></returns>
        public static Expression <Func <TDbType, bool> > BuildPredicate <TDbType>(object searchCriteria, IPredicateParser predicateParser, bool includeNullValues)
        {
            var filterDictionary = searchCriteria.ToFilterDictionary(includeNullValues);

            return(BuildPredicate <TDbType>(filterDictionary, predicateParser));
        }
        public static Expression <Func <TDbType, bool> > BuildPredicate <TDbType>(Dictionary <string, string> searchCriteria, IPredicateParser predicateParser)
        {
            var predicateOuter       = PredicateBuilder.New <TDbType>(true);
            var predicateErrorFields = new List <string>();
            var dict = searchCriteria;    // as Dictionary<string, string>;

            if (dict == null || !dict.Any())
            {
                return(predicateOuter);
            }
            var searchFields = typeof(TDbType).GetProperties();

            foreach (var searchField in searchFields)
            {
                // Get the name of the DB field, which may not be the same as the property name.
                var dbFieldName       = GetDbFieldName(searchField);
                var dbType            = typeof(TDbType);
                var dbFieldMemberInfo = dbType.GetMember(dbFieldName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).SingleOrDefault();
                if (dbFieldMemberInfo == null || !dict.ContainsKey(dbFieldMemberInfo.Name))
                {
                    continue;
                }
                var predicateValue = dict[dbFieldMemberInfo.Name];
                if (predicateValue == null)
                {
                    continue;
                }
                var rangesAllowed = searchField.PropertyType != typeof(string);
                if (!predicateParser.Parse(predicateValue, rangesAllowed, searchField.PropertyType))
                {
                    predicateErrorFields.Add(dbFieldMemberInfo.Name);
                    continue;
                }
                if (!predicateParser.Items.Any())
                {
                    continue;
                }
                var predicateInner = BuildInnerPredicate <TDbType>(predicateParser, searchField, dbFieldMemberInfo);
                if (predicateInner == null)
                {
                    continue;
                }
                predicateOuter = predicateOuter.And(predicateInner);
            }
            return(predicateOuter);
        }
 public NotebookService(IPredicateParser predicateParser, IDataAccess context)
 {
     this._predicateParser = predicateParser;
     this._context         = context;
 }