Beispiel #1
0
        public static Expression[] NavigationExpression(CompileContext context)
        {
            /**
             *      ***Navigation
             *      if(concreteQuery.UserQuery != null)
             *     {
             *          {
             *              var naviQuery = concreteQuery.UserQuery;
             *              if(naviQuery.Id != null){
             *                  source = source.Where(t=>t.User.Id == naviQuery.Id);
             *              }
             *              if(naviQuery.RoleQuery != null){
             *					var naviQuery_2 = naviQuery.RoleQuery;
             *
             *              }
             *          }
             *      }
             */
            if (context.Depth >= 4)
            {
                return(null);
            }
            var suffix          = "Query";
            var modelProperties = context.ModelProperties;
            var blocks          = new List <Expression>();
            var sourceParam     = context.SourceParam;

            foreach (var queryProperty in context.QueryProperties.Where(p => p.Name.EndsWith(suffix)))
            {
                var queryPropertyName = queryProperty.Name;
                foreach (var modelProperty in modelProperties)
                {
                    if (queryPropertyName == modelProperty.Name + suffix && typeof(BaseQuery).IsAssignableFrom(queryProperty.PropertyType))
                    {
                        var naviBlocks     = new List <Expression>();
                        var naviQueryParam = Expression.Parameter(queryProperty.PropertyType,
                                                                  "naviQuery_" + (context.Depth + 1));
                        var naviContext = new CompileContext()
                        {
                            Depth           = context.Depth + 1,
                            ModelProperties = modelProperty.PropertyType.GetProperties(),
                            ModelType       = context.ModelType,
                            QueryParam      = naviQueryParam,
                            QueryProperties = queryProperty.PropertyType.GetProperties(),
                            SourceParam     = sourceParam,
                            Navigations     = context.Navigations.Concat(new [] { modelProperty.Name }).ToArray()
                        };
                        naviBlocks.Add(Expression.Assign(naviQueryParam, Expression.Property(context.QueryParam, queryPropertyName)));
                        naviBlocks.AddRange(EqualExprssion(naviContext));
                        naviBlocks.AddRange(StringContainExpression(naviContext));
                        naviBlocks.AddRange(ListContainsExpression(naviContext));
                        naviBlocks.AddRange(RangeExpression(naviContext));
                        blocks.Add(Expression.Block(new[] { naviQueryParam }, naviBlocks));
                    }
                }
            }
            return(blocks.ToArray());
        }
Beispiel #2
0
        public static Expression[] StringContainExpression(CompileContext context)
        {
            /*      ----    StringContains
             *      if(concreteQuery.NamePattern != null){
             *          source = source.Where(o=>o.Name.Contains(concreteQuery.NamePattern));
             *      }
             */
            var suffix              = "Pattern";
            var modelProperties     = context.ModelProperties;
            var blocks              = new List <Expression>();
            var queryParam          = context.QueryParam;
            var sourceParam         = context.SourceParam;
            var modelType           = context.ModelType;
            var stringContainMethod = typeof(string).GetMethod("Contains");
            Func <Expression, Expression> modelAccess = expr => context.Navigations.Aggregate(expr, Expression.Property);

            foreach (var queryProperty in context.QueryProperties.Where(p => p.Name.EndsWith(suffix)))
            {
                var queryPropertyName = queryProperty.Name;
                foreach (var modelProperty in modelProperties)
                {
                    if (queryPropertyName == modelProperty.Name + suffix &&
                        modelProperty.PropertyType == typeof(string) &&
                        queryProperty.PropertyType == typeof(string))
                    {
                        var whereMethod = WhereMethod(modelType);

                        var t           = Expression.Parameter(modelType, "t");
                        var predictExpr = Expression.Lambda(
                            Expression.Call(Expression.Property(modelAccess(t), modelProperty),
                                            stringContainMethod,
                                            new Expression[] { Expression.Property(queryParam, queryProperty) }
                                            ),
                            t
                            );

                        var expr =
                            Expression.IfThen(
                                Expression.NotEqual(
                                    Expression.Property(queryParam, queryProperty),
                                    Expression.Constant(null)),
                                Expression.Assign(sourceParam,
                                                  Expression.Call(whereMethod,
                                                                  new Expression[] { sourceParam, predictExpr })
                                                  ));
                        blocks.Add(expr);
                    }
                }
            }
            return(blocks.ToArray());
        }
Beispiel #3
0
        public static Expression[] EqualExprssion(CompileContext context)
        {
            /**
             * *      ----   Equals
             *      if(concreteQuery.ID != null){
             *          source = source.Where(o=>concreteQuery.ID == o.ID);
             *      }
             */

            var modelProperties = context.ModelProperties;
            var blocks          = new List <Expression>();
            var queryParam      = context.QueryParam;
            var sourceParam     = context.SourceParam;
            var modelType       = context.ModelType;
            Func <Expression, Expression> modelAccess = expr => context.Navigations.Aggregate(expr, Expression.Property);

            foreach (var queryProperty in context.QueryProperties)
            {
                var queryPropertyName = queryProperty.Name;
                foreach (var modelProperty in modelProperties)
                {
                    if (queryPropertyName == modelProperty.Name)
                    {
                        var whereMethod = WhereMethod(modelType);

                        var t = Expression.Parameter(modelType, "t");

                        var predictExpr = Expression.Lambda(
                            typeof(Func <,>).MakeGenericType(new Type[] { modelType, typeof(bool) }),
                            Expression.Equal(Expression.Property(queryParam, queryProperty),
                                             Expression.Property(modelAccess(t), modelProperty)),
                            t

                            );
                        var expr =
                            Expression.IfThen(
                                Expression.NotEqual(
                                    Expression.Property(queryParam, queryProperty),
                                    Expression.Constant(null)),
                                Expression.Assign(sourceParam,
                                                  Expression.Call(whereMethod, new Expression[] { sourceParam, predictExpr })
                                                  ));
                        blocks.Add(expr);
                    }
                }
            }
            return(blocks.ToArray());
        }
Beispiel #4
0
        /*
         *
         * IQueryable<TModel> DynamicFunc<TModel>(IQuery<TModel> query, IQueryable<TModel> source)
         * {
         *      var concreteQuery = query as ConcreteQueryType;
         *      ----    Contains
         *      if(concreteQuery.IDs != null)
         *     {
         *          source = source.Where(o=>concreteQuery.IDList.Contains(o.ID));
         *      }
         *      ----   Equals
         *      if(concreteQuery.ID != null){
         *          source = source.Where(o=>concreteQuery.ID == o.ID);
         *      }
         *      ----    StringContains
         *      if(concreteQuery.NamePattern != null){
         *          source = source.Where(o=>o.Name.Contains(concreteQuery.NamePattern));
         *      }
         *      ----    Range
         *      if(concreteQuery.CreateAtRange != null){
         *          if(concreteQuery.CreateAtRange.Left != null){
         *              source = concreteQuery.LeftOpen??source.Where(o=>o.CreateAt > concreteQuery.CreateAtRange.Left):source.Where(o=>o.CreateAtRange>=concreteQuery.CreateAtRange.Left);
         *          }
         *          if(concreteQuery.CreateAtRange.Right != null){
         *              source = concreteQuery.RightOpen??source.Where(o=>o.CreateAt < concreteQuery.CreateAtRange.Right):source.Where(o=>o.CreateAtRange<=concreteQuery.CreateAtRange.Left);
         *      }
         *      ----    Take
         *      if(concreteQuery.Take != null){
         *          source = sourc.Take(concreteQuery.Take);
         *      }
         *      ----    Skip
         *      if(concreteQuery.Skip != null){
         *          source = sourc.Skip(concreteQuery.Skip);
         *      }
         *      ----    Order
         *      if(concreteQuery.OrderField != null){
         *          if(concreteQuery.OrderField == 'ID'){
         *              source = (concreteQuery.OrderDirection == OrderDirection.ASC)?source.OrderBy(o=>o.ID):source.OrderByDescending(o=>o.ID);
         *          }
         *      }
         *      return source;
         * }
         */
        public static Func <IQueryable <TModel>, BaseQuery <TModel>, IQueryable <TModel> > Compile <TModel>(BaseQuery query)
            where TModel : BaseEntity
        {
            Func <IQueryable <TModel>, BaseQuery <TModel>, IQueryable <TModel> > handler = null;
            var concreteQueryType = query.GetType();
            var modelType         = query.ModelType;
            var queryProperties   = concreteQueryType.GetProperties();
            var modelProperties   = modelType.GetProperties();
            var queryParamExpr    = Expression.Parameter(typeof(BaseQuery <TModel>), "query");
            var concreteQueryExpr = Expression.Parameter(concreteQueryType, "concreteQuery");
            var sourceParamExpr   = Expression.Parameter(typeof(IQueryable <TModel>), "source");
            var context           = new CompileContext()
            {
                ModelProperties = modelProperties,
                QueryProperties = queryProperties,
                QueryParam      = concreteQueryExpr,
                SourceParam     = sourceParamExpr,
                ModelType       = modelType,
                Depth           = 1,
                Navigations     = new string[0]
            };

            //Handle Equals
            var blocks = new List <Expression>()
            {
                Expression.Assign(concreteQueryExpr, Expression.Convert(queryParamExpr, concreteQueryType))
            };

            blocks.AddRange(EqualExprssion(context));
            blocks.AddRange(StringContainExpression(context));
            blocks.AddRange(ListContainsExpression(context));
            blocks.AddRange(RangeExpression(context));
            blocks.AddRange(PaginationExpression(context));
            blocks.AddRange(NavigationExpression(context));
            blocks.Add(sourceParamExpr);
            var expr = Expression.Lambda(
                Expression.Block(new[] { concreteQueryExpr }, blocks), new[] { sourceParamExpr, queryParamExpr }
                );

            handler = (Func <IQueryable <TModel>, BaseQuery <TModel>, IQueryable <TModel> >)expr.Compile();
            return(handler);
        }
Beispiel #5
0
        public static Expression[] PaginationExpression(CompileContext context)
        {
            var blocks = new List <Expression>();

            /*
             *      ----    Take
             *      if(concreteQuery.Take != null){
             *          source = sourc.Take(concreteQuery.Take);
             *      }
             *      ----    Skip
             *      if(concreteQuery.Skip != null){
             *          source = sourc.Skip(concreteQuery.Skip);
             *      }
             *      ----    Order
             *      if(concreteQuery.OrderField != null){
             *          if(concreteQuery.OrderField == 'ID'){
             *              source = (concreteQuery.OrderDirection == OrderDirection.ASC)?source.OrderBy(o=>o.ID):source.OrderByDescending(o=>o.ID);
             *          }
             *      }
             *      query.Count = source.Count();
             */
            var queryParam           = context.QueryParam;
            var sourceParam          = context.SourceParam;
            var modelType            = context.ModelType;
            var defaultOrderField    = "Id";
            var canOrderedProperties = context.ModelProperties.Where(
                pi => pi.PropertyType == typeof(string) || pi.PropertyType.IsValueType).ToArray();
            var stringIsNullOrEmptyMethod = typeof(string).GetMethod("IsNullOrEmpty");
            var orderFieldProperty        = Expression.Property(queryParam, "OrderField");
            var orderDirectionProperty    = Expression.Property(queryParam, "OrderDirection");
            var orderByMethod             =
                typeof(Queryable).GetMethods().FirstOrDefault(mi => mi.Name == "OrderBy");
            var orderByDescendingMethod =
                typeof(Queryable).GetMethods()
                .FirstOrDefault(mi => mi.Name == "OrderByDescending");
            var orderFieldParam   = Expression.Parameter(typeof(string), "orderField");
            var directionParam    = Expression.Parameter(typeof(OrderDirection), "direction");
            var exprAssignDefault = Expression.Condition(
                Expression.Call(
                    stringIsNullOrEmptyMethod,
                    new Expression[] { orderFieldProperty }
                    ),
                Expression.Assign(orderFieldParam, Expression.Constant(defaultOrderField)),
                Expression.Assign(orderFieldParam, orderFieldProperty)
                );

            blocks.Add(exprAssignDefault);
            blocks.Add(Expression.Condition(
                           Expression.Equal(orderDirectionProperty, Expression.Constant(null)),
                           Expression.Assign(directionParam, Expression.Constant(OrderDirection.ASC)),
                           Expression.Assign(directionParam, Expression.Property(orderDirectionProperty, "Value"))
                           ));
            var tempParam      = Expression.Parameter(modelType, "t");
            var switchCaseExpr =
                canOrderedProperties.Select(
                    property =>
                    Expression.SwitchCase(
                        Expression.Condition(
                            Expression.NotEqual(directionParam,
                                                Expression.Constant(OrderDirection.DESC)),
                            Expression.Assign(sourceParam,
                                              Expression.Call(
                                                  orderByMethod.MakeGenericMethod(new[]
                                                                                  { modelType, property.PropertyType }),
                                                  sourceParam,
                                                  Expression.Lambda(
                                                      Expression.Property(tempParam,
                                                                          property.Name),
                                                      tempParam))),
                            Expression.Assign(sourceParam,
                                              Expression.Call(
                                                  orderByDescendingMethod
                                                  .MakeGenericMethod(new[] { modelType, property.PropertyType }),
                                                  sourceParam,
                                                  Expression.Lambda(
                                                      Expression.Property(tempParam,
                                                                          property.Name),
                                                      tempParam)))),
                        Expression.Constant(property.Name))
                    ).ToArray();
            var switchExpr =
                Expression.Switch(orderFieldParam,
                                  Expression.Assign(sourceParam, sourceParam),
                                  switchCaseExpr
                                  );

            blocks.Add(switchExpr);

            blocks.Add(Expression.Assign(sourceParam,
                                         Expression.Call(
                                             typeof(Compiler).GetMethod("PagerHandler").MakeGenericMethod(modelType),
                                             sourceParam, queryParam)));

            var blockExpr = Expression.Block(new ParameterExpression[] { orderFieldParam, directionParam }, blocks);



            return(new Expression[] { blockExpr });
        }
Beispiel #6
0
        public static Expression[] RangeExpression(CompileContext context)
        {
            /*      ----    Range
             *      if(concreteQuery.CreateAtRange != null){
             *          if(concreteQuery.CreateAtRange.Left != null){
             *              source = concreteQuery.LeftOpen??source.Where(o=>o.CreateAt > concreteQuery.CreateAtRange.Left):source.Where(o=>o.CreateAtRange>=concreteQuery.CreateAtRange.Left);
             *          }
             *          if(concreteQuery.CreateAtRange.Right != null){
             *              source = concreteQuery.RightOpen??source.Where(o=>o.CreateAt < concreteQuery.CreateAtRange.Right):source.Where(o=>o.CreateAtRange<=concreteQuery.CreateAtRange.Left);
             *      }
             */
            var suffix          = "Range";
            var modelProperties = context.ModelProperties;
            var blocks          = new List <Expression>();
            var queryParam      = context.QueryParam;
            var sourceParam     = context.SourceParam;
            var modelType       = context.ModelType;
            var whereMethod     = WhereMethod(modelType);
            Func <Expression, Expression> modelAccess = expr => context.Navigations.Aggregate(expr, Expression.Property);

            foreach (var queryProperty in context.QueryProperties.Where(p => p.Name.EndsWith(suffix)))
            {
                var queryPropertyName = queryProperty.Name;
                foreach (var modelProperty in modelProperties)
                {
                    if (queryPropertyName == modelProperty.Name + suffix &&
                        queryProperty.PropertyType.GetGenericTypeDefinition() == typeof(Range <>))
                    {
                        var t = Expression.Parameter(modelType, "t");
                        var leftLargerThan =
                            Expression.Call(whereMethod,
                                            new Expression[]
                        {
                            sourceParam,
                            Expression.Lambda(Expression.GreaterThan(
                                                  Expression.Property(modelAccess(t), modelProperty),
                                                  Expression.Property(
                                                      Expression.Property(queryParam, queryProperty), "Left")
                                                  ),
                                              t)
                        });
                        var leftLargerThanOrEqual =
                            Expression.Call(whereMethod,
                                            new Expression[]
                        {
                            sourceParam,
                            Expression.Lambda(Expression.GreaterThanOrEqual(
                                                  Expression.Property(modelAccess(t), modelProperty),
                                                  Expression.Property(
                                                      Expression.Property(queryParam,
                                                                          queryProperty),
                                                      "Left")
                                                  ), t)
                        }
                                            );
                        var rightLessThan =
                            Expression.Call(whereMethod,
                                            new Expression[]
                        {
                            sourceParam,
                            Expression.Lambda(Expression.LessThan(
                                                  Expression.Property(modelAccess(t), modelProperty),
                                                  Expression.Property(
                                                      Expression.Property(queryParam, queryProperty), "Right")
                                                  ), t)
                        }
                                            );
                        var rightLessThanOrEuqal =
                            Expression.Call(whereMethod,
                                            new Expression[]
                        {
                            sourceParam,
                            Expression.Lambda(Expression.LessThanOrEqual(
                                                  Expression.Property(modelAccess(t), modelProperty),
                                                  Expression.Property(
                                                      Expression.Property(queryParam, queryProperty), "Right")), t)
                        }
                                            );
                        var expr =
                            Expression.IfThen(
                                Expression.NotEqual(
                                    Expression.Property(queryParam, queryProperty),
                                    Expression.Constant(null)),
                                Expression.Block(new Expression[]
                        {
                            Expression.IfThen(
                                Expression.NotEqual(
                                    Expression.Property(Expression.Property(queryParam, queryProperty),
                                                        "Left"),
                                    Expression.Constant(null)
                                    ),
                                Expression.IfThenElse(
                                    Expression.Property(Expression.Property(queryParam, queryProperty),
                                                        "LeftOpen"),
                                    Expression.Assign(
                                        sourceParam,
                                        leftLargerThan
                                        ),
                                    Expression.Assign(
                                        sourceParam,
                                        leftLargerThanOrEqual
                                        )
                                    )),
                            Expression.IfThen(
                                Expression.NotEqual(
                                    Expression.Property(Expression.Property(queryParam, queryProperty),
                                                        "Right"),
                                    Expression.Constant(null)
                                    ),
                                Expression.IfThenElse(
                                    Expression.Property(Expression.Property(queryParam, queryProperty),
                                                        "RightOpen"),
                                    Expression.Assign(
                                        sourceParam,
                                        rightLessThan
                                        ),
                                    Expression.Assign(
                                        sourceParam,
                                        rightLessThanOrEuqal
                                        )
                                    )
                                )
                        })
                                );
                        blocks.Add(expr);
                    }
                }
            }
            return(blocks.ToArray());
        }
Beispiel #7
0
        public static Expression[] ListContainsExpression(CompileContext context)
        {
            /**
             *      ***Contains
             *      if(concreteQuery.IDs != null)
             *     {
             *          source = source.Where(o=>concreteQuery.IDList.Contains(o.ID.Value));
             *      }
             */

            var suffix          = "List";
            var modelProperties = context.ModelProperties;
            var blocks          = new List <Expression>();
            var queryParam      = context.QueryParam;
            var sourceParam     = context.SourceParam;
            var modelType       = context.ModelType;
            var cm = typeof(Enumerable).GetMethods().FirstOrDefault(mi => mi.Name == "Contains");
            Func <Expression, Expression> modelAccess = expr => context.Navigations.Aggregate(expr, Expression.Property);

            foreach (var queryProperty in context.QueryProperties.Where(p => p.Name.EndsWith(suffix)))
            {
                var queryPropertyName = queryProperty.Name;
                foreach (var modelProperty in modelProperties)
                {
                    var containsMethod = cm;
                    if (queryPropertyName == modelProperty.Name + suffix &&
                        queryProperty.PropertyType.IsArray &&
                        (queryProperty.PropertyType.GetElementType() == modelProperty.PropertyType ||
                         queryProperty.PropertyType.GetElementType() == Nullable.GetUnderlyingType(modelProperty.PropertyType)))
                    {
                        var        whereMethod = WhereMethod(modelType);
                        var        t           = Expression.Parameter(modelType, "t");
                        Expression predictExpr;
                        if (modelProperty.PropertyType == typeof(string))
                        {
                            containsMethod = containsMethod.MakeGenericMethod(typeof(string));
                            predictExpr    = Expression.Lambda(
                                Expression.Call(
                                    containsMethod,
                                    Expression.Property(queryParam, queryProperty),
                                    Expression.Property(modelAccess(t), modelProperty)
                                    ),
                                t
                                );
                        }
                        else
                        {
                            containsMethod =
                                containsMethod.MakeGenericMethod(queryProperty.PropertyType.GetElementType());
                            predictExpr = Expression.Lambda(
                                Expression.Call(
                                    containsMethod,
                                    Expression.Property(queryParam, queryProperty),
                                    Expression.Property(Expression.Property(modelAccess(t), modelProperty), "Value")
                                    ),
                                t
                                );
                        }
                        var expr =
                            Expression.IfThen(
                                Expression.NotEqual(
                                    Expression.Property(queryParam, queryProperty),
                                    Expression.Constant(null)),
                                Expression.Assign(sourceParam,
                                                  Expression.Call(whereMethod,
                                                                  new Expression[] { sourceParam, predictExpr })
                                                  ));
                        blocks.Add(expr);
                    }
                }
            }
            return(blocks.ToArray());
        }