/// <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); }
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); }
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); }
/// <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); }
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)); }
/// <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)); }