Ejemplo n.º 1
0
        /// <summary>
        /// 返回模型对应的主键字段名
        /// </summary>
        /// <returns>返回模型的主键列信息</returns>
        internal static Expression <Func <T, bool> > GetKeysExpression <T>(T entity)
        {
            var keyMeta = MapperConfig.GetKeyMetas <T>();

            if (keyMeta == null)
            {
                throw Error.Exception("没有为模型" + typeof(T).FullName + "指定主键。");
            }

            LambdaExpression    body      = null;
            ParameterExpression parameter = null;

            for (var i = 0; i < keyMeta.Length; i++)
            {
                var meta = keyMeta[i];
                if (meta.Expression is LambdaExpression exp)
                {
                    parameter = exp.Parameters.FirstOrDefault();
                    var key    = exp.Compile().DynamicInvoke(entity);
                    var keyExp = Expression.Constant(key);
                    //var keyExp = Expression.MakeMemberAccess(constvar, meta.Member);
                    var mem         = exp.Body.ChangeType(keyExp.Type);
                    var condition   = Expression.Equal(keyExp, mem);
                    var innerLambda = Expression.Lambda(condition, parameter);

                    body = body.AndAlso(innerLambda);
                }
            }

            if (body != null)
            {
                return(Expression.Lambda <Func <T, bool> >(body.Body, parameter));
            }
            return(null);
        }
Ejemplo n.º 2
0
        internal static LambdaExpression BuildExpression(this Type entitytype, string[] filters, bool rev)
        {
            LambdaExpression lambdaExpression = null;
            var usefilters = rev ?
                             GlobaQuerylFilters.Filters.Where(x => filters.Contains(x.Key)) :
                             GlobaQuerylFilters.Filters.Where(x => !filters.Contains(x.Key));

            foreach (var f in usefilters)
            {
                var ftype = f.Value.FilterType;
                if (ftype.IsAssignableFrom(entitytype))
                {
                    var visitor = new ParameterTypeVisitor(ftype, entitytype);
                    var a       = (LambdaExpression)visitor.Visit(f.Value.Expression);

                    if (lambdaExpression == null)
                    {
                        lambdaExpression = a;
                    }
                    else
                    {
                        lambdaExpression = lambdaExpression.AndAlso(a);
                    }
                }
            }

            return(lambdaExpression);
        }
Ejemplo n.º 3
0
        private static Expression <Func <T, bool> > AddDocTypePredicate(Expression <Func <T, bool> > predicate)
        {
            var type              = typeof(T);
            var docTypeField      = type.GetProperty("_docType");
            var memberExp         = Expression.Property(predicate.Parameters[0], docTypeField);
            var secondPredicate   = LambdaExpression.Equal(memberExp, Expression.Constant(type.Name));
            var and               = LambdaExpression.AndAlso(predicate.Body, secondPredicate);
            var extendedPredicate = Expression.Lambda <Func <T, bool> >(and, predicate.Parameters);

            return(extendedPredicate);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 返回模型对应的主键字段名
        /// </summary>
        /// <returns>返回模型的主键列信息</returns>
        internal static Expression <Func <T, bool> > GetKeysExpression <T>(params object[] keys)
        {
            var keyMeta = MapperConfig.GetKeyMetas <T>();

            if (keyMeta == null)
            {
                throw Error.Exception("没有为模型" + typeof(T).FullName + "指定主键。");
            }

            if (keys.Length != keyMeta.Length)
            {
                return(null);
                //throw Error.Exception("主键的列数目和给定的键值数目不相等。");
            }

            LambdaExpression    body      = null;
            ParameterExpression parameter = null;

            for (var i = 0; i < keyMeta.Length; i++)
            {
                var meta = keyMeta[i];
                if (meta.Expression is LambdaExpression exp)
                {
                    parameter = exp.Parameters.FirstOrDefault();
                    var keyExp      = Expression.Constant(keys[i]);
                    var mem         = exp.Body.ChangeType(keyExp.Type);
                    var condition   = Expression.Equal(keyExp, mem);
                    var innerLambda = Expression.Lambda(condition, parameter);

                    body = body.AndAlso(innerLambda);
                }
            }

            if (body != null)
            {
                return(Expression.Lambda <Func <T, bool> >(body.Body, parameter));
            }
            return(null);
        }
Ejemplo n.º 5
0
        private static KeyValuePair <Expression, MutatorConfiguration> PurgeFilters(Expression path, MutatorConfiguration mutator)
        {
            var filters     = new List <LambdaExpression>();
            var cleanedPath = path.CleanFilters(filters);

            if (filters.Any(filter => filter != null))
            {
                var shards                 = path.SmashToSmithereens();
                var cleanedShards          = cleanedPath.SmashToSmithereens();
                var aliases                = new List <KeyValuePair <Expression, Expression> >();
                var i                      = 0;
                var j                      = 0;
                LambdaExpression condition = null;
                foreach (var filter in filters)
                {
                    while (!(shards[i].NodeType == ExpressionType.Call && (((MethodCallExpression)shards[i]).Method.IsCurrentMethod() || ((MethodCallExpression)shards[i]).Method.IsEachMethod())))
                    {
                        ++i;
                    }
                    while (!(cleanedShards[j].NodeType == ExpressionType.Call && (((MethodCallExpression)cleanedShards[j]).Method.IsCurrentMethod() || ((MethodCallExpression)cleanedShards[j]).Method.IsEachMethod())))
                    {
                        ++j;
                    }
                    if (filter == null)
                    {
                        continue;
                    }
                    aliases.Add(new KeyValuePair <Expression, Expression>(cleanedShards[j], shards[i]));
                    condition = condition == null ? filter : condition.AndAlso(filter, false);
                    ++i;
                    ++j;
                }

                mutator = mutator.ResolveAliases(new LambdaAliasesResolver(aliases)).If(condition);
            }

            return(new KeyValuePair <Expression, MutatorConfiguration>(cleanedPath, mutator));
        }
Ejemplo n.º 6
0
        /// <summary>
        ///     Выкидываем вызовы Select и Where, заменяя их на на Current.
        ///     Из всех Where строим жирную лямбду и скидываем её в filter.
        ///     <code>
        ///     qxx.Data.Where(x => x.EndsWith("GRobas")).Select(x => x.ToArray()).Where(x => x.Length > 0).Each().Current() ->
        ///         qxx.Data.Current().ToArray().Current()
        ///         filter = qxx.Data.Current().EndsWith("GRobas") && qxx.Data.Current().ToArray().Length > 0
        /// </code>
        /// </summary>
        public static LambdaExpression SimplifyPath(LambdaExpression path, out LambdaExpression filter)
        {
            filter = null;
            var shards = path.Body.SmashToSmithereens();
            int i;

            for (i = 0; i < shards.Length; ++i)
            {
                if (shards[i].NodeType == ExpressionType.Call && ((MethodCallExpression)shards[i]).Method.DeclaringType == typeof(Enumerable))
                {
                    break;
                }
            }

            if (i >= shards.Length)
            {
                return(path);
            }
            var result   = shards[i - 1];
            var currents = 0;

            for (; i < shards.Length; ++i)
            {
                var shard = shards[i];
                switch (shard.NodeType)
                {
                case ExpressionType.MemberAccess:
                    result = Expression.MakeMemberAccess(result, ((MemberExpression)shard).Member);
                    break;

                case ExpressionType.ArrayIndex:
                    result = Expression.ArrayIndex(result, ((BinaryExpression)shard).Right);
                    break;

                case ExpressionType.Call:
                    var methodCallExpression = (MethodCallExpression)shard;
                    var method = methodCallExpression.Method;
                    if (method.DeclaringType == typeof(Enumerable))
                    {
                        switch (method.Name)
                        {
                        case "Select":
                            // Substitute call to Select method with Current
                            // arr.Select(x => x.y) -> arr.Current().y
                            var selector = (LambdaExpression)methodCallExpression.Arguments[1];
                            result =
                                Expression.Lambda(
                                    Expression.Call(
                                        MutatorsHelperFunctions.CurrentMethod.MakeGenericMethod(result.Type.GetItemType()), result), path.Parameters)
                                .Merge(selector)
                                .Body;
                            ++currents;
                            break;

                        case "Where":
                            // Remove call to Where, saving it to filter
                            // arr.Where(x => x.y > 0) ->
                            // result := arr
                            // filter := filter && (arr.Current().y > 0)
                            //
                            // If we had Select call replaced by Current, new Current call is not added
                            // arr.Select(x => x.y).Where(y => y.z > 0) -> arr.Current().y.Where(y => y.z > 0) ->
                            // result = arr.Current().y
                            // filter := filter && arr.Current().y.z > 0
                            var predicate      = (LambdaExpression)methodCallExpression.Arguments[1];
                            var callExpression = result.Type == predicate.Parameters[0].Type
                                                     ? result
                                                     : Expression.Call(MutatorsHelperFunctions.CurrentMethod.MakeGenericMethod(result.Type.GetItemType()), result);
                            var currentFilter = Expression.Lambda(callExpression, path.Parameters).Merge(predicate);
                            filter = filter == null ? currentFilter : filter.AndAlso(currentFilter, false);
                            break;

                        default:
                            throw new NotSupportedException(string.Format("Method '{0}' is not supported", method));
                        }
                    }
                    else if (method.DeclaringType == typeof(MutatorsHelperFunctions))
                    {
                        switch (method.Name)
                        {
                        case "Current":
                        case "Each":
                            // Remove Each/Current call if it is added before by processing of Select/Where calls.
                            --currents;
                            if (currents < 0)
                            {
                                result = Expression.Call(method.GetGenericMethodDefinition().MakeGenericMethod(result.Type.GetItemType()), result);
                                ++currents;
                            }

                            break;

                        default:
                            throw new NotSupportedException(string.Format("Method '{0}' is not supported", method));
                        }
                    }
                    else
                    {
                        throw new NotSupportedException(string.Format("Method '{0}' is not supported", method));
                    }

                    break;

                case ExpressionType.ArrayLength:
                    result = Expression.ArrayLength(result);
                    break;

                case ExpressionType.Convert:
                    result = Expression.Convert(result, shard.Type);
                    break;

                default:
                    throw new NotSupportedException(string.Format("Node type '{0}' is not valid at this point", shard.NodeType));
                }
            }

            return(Expression.Lambda(result, path.Parameters));
        }