private static Func <T1, T1, bool> CreateMatchExpression <T1>(List <LambdaExpression> expressions) { Expression buildExpr = null; var param1 = Expression.Parameter(typeof(T1), "p1"); var param2 = Expression.Parameter(typeof(T1), "p2"); for (int i = 0; i < expressions.Count; i++) { var left = ParameterReplacer.Replace(expressions[i], expressions[i].Parameters.First(), param1) as LambdaExpression; var right = ParameterReplacer.Replace(expressions[i], expressions[i].Parameters.First(), param2) as LambdaExpression; var expr = Expression.Equal(left.Body, right.Body); if (buildExpr == null) { buildExpr = expr; } else { buildExpr = Expression.AndAlso(buildExpr, expr); } } var lambda = Expression.Lambda <Func <T1, T1, bool> >(buildExpr, param1, param2); var func = lambda.Compile(); return(func); }
public static Expression <Func <TTarget, TResult> > ConvertGenericTypeArgument <TSource, TTarget, TResult>( this Expression <Func <TSource, TResult> > root) { var visitor = new ParameterReplacer(typeof(TSource), typeof(TTarget)); return(visitor.Visit(root) as Expression <Func <TTarget, TResult> >); }
private static Func <T1, T2, bool> CreateMatchExpression <T1, T2>(ParameterExpression oldParam, List <Expression> leftExpressions, List <Expression> rightExpressions) { Expression buildExpr = null; var param1 = Expression.Parameter(typeof(T1), "p1"); var param2 = Expression.Parameter(typeof(T2), "p2"); for (int i = 0; i < leftExpressions.Count; i++) { var left = ParameterReplacer.Replace(leftExpressions[i], oldParam, param1); var right = ParameterReplacer.Replace(rightExpressions[i], oldParam, param2); var expr = Expression.Equal(left, right); if (buildExpr == null) { buildExpr = expr; } else { buildExpr = Expression.AndAlso(buildExpr, expr); } } var lambda = Expression.Lambda <Func <T1, T2, bool> >(buildExpr, param1, param2); var func = lambda.Compile(); return(func); }
public static Expression ReplaceFirstParam(this LambdaExpression expression, Expression newParameter) { var parameterToRemove = expression.Parameters.ElementAt(0); var replacer = new ParameterReplacer(parameterToRemove, newParameter); return(replacer.Visit(expression.Body)); }
public LambdaExpression GetExpression(Dictionary <string, object> enviromens = null) { var enityType = Type.GetType(EntityType); List <LambdaExpression> lambdaExpressions = new List <LambdaExpression>(); foreach (var item in NestedRules) { lambdaExpressions.Add(item.GetExpression(enviromens)); } foreach (var item in Rules) { lambdaExpressions.Add(item.GetExpression(enviromens)); } Expression expression = null; foreach (var item in lambdaExpressions) { if (expression == null) { expression = item.Body; continue; } expression = ConditionType == Query.Condition.OrElse ? Expression.OrElse(expression, item.Body) : Expression.AndAlso(expression, item.Body); } var parameter = Expression.Parameter(enityType, QueryCollection.ParameterSymbol); expression = new ParameterReplacer(parameter).Replace(expression); return(Expression.Lambda(expression, parameter)); }
/// <summary> /// コンストラクタ、親ノードと結合種類、テーブル、結合式を指定して初期化する /// </summary> /// <param name="parent">親ノード</param> /// <param name="joinType">結合種類</param> /// <param name="table">結合するテーブル</param> /// <param name="on">結合式</param> public Join(IQueryNode parent, JoinType joinType, ITable <TColumns> table, Expression <Func <TColumns, bool> > on) { var select = table as ISelect <TColumns>; if (select is null) { table = table.AliasedClone(); } else { QueryNodeHelper.SwitchParent(select, this); } this.Parent = parent; this.JoinType = joinType; this.Table = table; this.Columns = table.Columns; this.Owner.RegisterTable(table); this.On = new ElementCode( ParameterReplacer.Replace( on.Body, new Dictionary <Expression, object> { { on.Parameters[0], table.Columns } } ), this.Owner.AllColumns ); }
public static Expression <Func <T1, TResult> > FixParam <T1, T2, TResult>(this Expression <Func <T1, T2, TResult> > expression, T2 parameterValue) { var parameterToRemove = expression.Parameters.ElementAt(1); var replacer = new ParameterReplacer(parameterToRemove, Expression.Constant(parameterValue, typeof(T2))); return(Expression.Lambda <Func <T1, TResult> >(replacer.Visit(expression.Body), expression.Parameters.Where(p => p != parameterToRemove))); }
static void Main() { IQueryable <string> strings = (new[] { "Jon", "Tom", "Holly", "Robin", "William" }).AsQueryable(); Expression <Func <string, bool> > firstPredicate = p => p.Contains("ll"); Expression <Func <string, bool> > secondPredicate = p => p.Length == 3; Expression combined = Expression.OrElse(firstPredicate.Body, secondPredicate.Body); ParameterExpression param = Expression.Parameter(typeof(string), "p"); ParameterReplacer replacer = new ParameterReplacer(param); combined = replacer.Visit(combined); var lambda = Expression.Lambda <Func <string, bool> >(combined, param); var query = strings.Where(lambda); foreach (string x in query) { Console.WriteLine(x); } }
public static Expression <Func <T, bool> > Combine <T>(Expression <Func <T, bool> > left, Expression <Func <T, bool> > right) { var parameter = Expression.Parameter(typeof(T), "p"); var combined = new ParameterReplacer(parameter).Visit(Expression.OrElse(left.Body, right.Body)); return(Expression.Lambda <Func <T, bool> >(combined, parameter)); }
/// <summary> /// Creates a new instance of the <see cref="SelectFilter{T, S}"/> class, /// that transposes the item type for the given filter and returns what it evaluates to. /// </summary> /// <param name="transpose">The function that transposes from T to S.</param> /// <param name="filter">The filter to evaluate.</param> public SelectFilter(Expression <Func <T, S> > transpose, Filter <S> filter) { var parameterReplacer = new ParameterReplacer(transpose.Parameters.Single(), Parameter); var compiledFilter = filter.GetCompiledFilter(); FilterExpression = compiledFilter.GetInvocation(parameterReplacer.Visit(transpose)); }
public static Expression <Func <TTo, bool> > CastParameter <TFrom, TTo>( this Expression <Func <TFrom, bool> > predicate) { var parameter = Expression.Parameter(typeof(TTo)); var body = new ParameterReplacer(parameter).Visit(predicate.Body); return(Expression.Lambda <Func <TTo, bool> >(body, parameter)); }
public static LambdaExpression ConvertGenericTypeArgument <TSource, TResult>( this Expression <Func <TSource, TResult> > root, Type targetType) { var visitor = new ParameterReplacer(typeof(TSource), targetType); var expression = visitor.Visit(root); return(expression as LambdaExpression); }
public From <TColumns> Where(Expression <Func <TColumns, bool> > expression) { var body = ParameterReplacer.Replace(expression.Body, new Dictionary <Expression, object> { { expression.Parameters[0], this.Columns } }); return(this.Where(new Where(this, body))); }
public SelectFrom <TSelectedColumns> Select <TSelectedColumns>(Expression <Func <TColumns, TSelectedColumns> > columnsExpression) { var expr = ParameterReplacer.Replace(columnsExpression.Body, new Dictionary <Expression, object> { { columnsExpression.Parameters[0], this.Columns } }); return(new SelectFrom <TSelectedColumns>(this, expr)); }
/// <summary> /// 组合表达式 /// </summary> /// <param name="first"></param> /// <param name="second"></param> /// <param name="compose"></param> /// <returns></returns> public static LambdaExpression Compose(this LambdaExpression first, LambdaExpression second, Func <Expression, Expression, Expression> compose) { var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); var secondBody = ParameterReplacer.ReplaceParameters(map, second.Body); return(Expression.Lambda(compose(first.Body, secondBody), first.Parameters)); }
public static Expression <Func <T, bool> > ToLambda <T>(this BinaryExpression binaryExpression) { var parameterExpression = Expression.Parameter(typeof(T)); var expression = new ParameterReplacer(parameterExpression).Visit(binaryExpression); return(Expression.Lambda <Func <T, bool> >(expression, parameterExpression)); }
/// <summary> /// コンストラクタ、親ノード、挿入先テーブルと列の並びを指定して初期化する /// </summary> /// <param name="parent">親ノード</param> /// <param name="table">挿入先テーブル</param> /// <param name="columnsExpression">列と設定値を指定する t => new[] { t.A == a, t.B == b } の様な式</param> public InsertInto(IQueryNode parent, TableDef <TColumns> table, Expression <Func <TColumns, bool[]> > columnsExpression) { this.Parent = parent; // new [] { bool, bool... } の様な形式以外はエラーとする var body = columnsExpression.Body; if (body.NodeType != ExpressionType.NewArrayInit) { throw new ApplicationException(); } // 登録 var owner = this.Owner; owner.RegisterTable(table); // bool[] の各要素初期化式を取得する var newexpr = body as NewArrayExpression; var expressions = newexpr.Expressions; var map = new Dictionary <Expression, object> { { columnsExpression.Parameters[0], table.Columns } }; var availableColumns = owner.AllColumns; var tableColumnMap = table.ColumnMap; var columnsOrder = new ColumnMap(); var values = new ElementCode[expressions.Count]; for (int i = 0; i < values.Length; i++) { // t.A == a の様に Equal を代入として扱いたいのでそれ以外はエラーとする var expression = expressions[i]; if (expression.NodeType != ExpressionType.Equal) { throw new ApplicationException(); } var binary = expression as BinaryExpression; // 左辺は代入先の列でなければならない var left = new ElementCode(ParameterReplacer.Replace(binary.Left, map), tableColumnMap); var column = left.FindColumns().FirstOrDefault(); if (column == null) { throw new ApplicationException(); } // 右辺は式 values[i] = new ElementCode(ParameterReplacer.Replace(binary.Right, map), availableColumns); // 列の生成元を右辺の式にして列を登録 columnsOrder.Add(column); } this.Table = table; this.ColumnMap = columnsOrder; this.ValueNode = new ValueSetter(this, columnsOrder, values); }
/// <summary> /// WHERE句の式を登録する /// </summary> /// <param name="expression">式</param> /// <returns>自分</returns> public From <TColumns> Where(Expression <Func <TColumns, bool> > expression) { var body = ParameterReplacer.Replace(expression.Body, new Dictionary <Expression, object> { { expression.Parameters[0], this.Columns } }); this.WhereNode = new Where(this, new ElementCode(body, this.Owner.AllColumns)); return(this); }
private static Expression <Func <A, C> > Compose <A, B, C>(Expression <Func <B, C> > f, Expression <Func <A, A, B> > g, ParameterExpression param) { var ex = ReplaceExpressions(f.Body, f.Parameters[0], g.Body); ex = new ParameterReplacer(param) .Visit(ex); return(Expression.Lambda <Func <A, C> >(ex, param)); }
private static void AddFieldWithIdArgumentIfExists <TContextType>(MappedSchemaProvider <TContextType> schema, Type contextType, Field fieldProp) { if (!fieldProp.Resolve.Type.IsEnumerableOrArray()) { return; } var schemaType = schema.Type(fieldProp.ReturnTypeClrSingle); // Find the first field named "id" or "<fieldProp.Name>Id" to turn into a field with arguments var idFieldDef = schemaType.GetFields().FirstOrDefault(f => f.Name.ToLower() == "id" || f.Name.ToLower() == $"{fieldProp.Name.ToLower()}id"); if (idFieldDef == null) { return; } // Save a little bit of typing and clean things up. var idFieldName = idFieldDef.Name; // We need to build an anonymous type with id = RequiredField<idFieldDef.Resolve.Type>() // Resulting lambda is (a, p) => a.Where(b => b.Id == p.Id).First() // This allows us to "insert" .Select() (and .Include()) before the .First() var requiredFieldType = typeof(RequiredField <>).MakeGenericType(idFieldDef.Resolve.Type); var fieldNameAndType = new Dictionary <string, Type> { { idFieldName, requiredFieldType } }; var argTypes = LinqRuntimeTypeBuilder.GetDynamicType(fieldNameAndType); var argTypesValue = argTypes.GetTypeInfo().GetConstructors()[0].Invoke(new Type[0]); var argTypeParam = Expression.Parameter(argTypes); Type arrayContextType = schema.Type(fieldProp.ReturnTypeClrSingle).ContextType; var arrayContextParam = Expression.Parameter(arrayContextType); var ctxId = Expression.PropertyOrField(arrayContextParam, $"{char.ToUpper(idFieldName[0])}{idFieldName.Substring(1)}"); Expression argId = Expression.PropertyOrField(argTypeParam, idFieldName); argId = Expression.Property(argId, "Value"); // call RequiredField<>.Value to get the real type without a convert var idBody = Expression.MakeBinary(ExpressionType.Equal, ctxId, argId); var idLambda = Expression.Lambda(idBody, new[] { arrayContextParam }); Expression body = ExpressionUtil.MakeExpressionCall(new[] { typeof(Queryable), typeof(Enumerable) }, "Where", new Type[] { arrayContextType }, fieldProp.Resolve, idLambda); body = ExpressionUtil.MakeExpressionCall(new[] { typeof(Queryable), typeof(Enumerable) }, "FirstOrDefault", new Type[] { arrayContextType }, body); var contextParam = Expression.Parameter(contextType); var lambdaParams = new[] { contextParam, argTypeParam }; body = new ParameterReplacer().ReplaceByType(body, contextType, contextParam); var selectionExpression = Expression.Lambda(body, lambdaParams); var name = fieldProp.Name.Singularize(); if (name == null) { // If we can't singularize it just use the name plus something as GraphQL doesn't support field overloads name = $"{fieldProp.Name}"; } var field = new Field(name, selectionExpression, $"Return a {fieldProp.ReturnTypeClrSingle} by its Id", fieldProp.ReturnTypeClrSingle, argTypesValue); schema.AddField(field); }
public void ParameterReplacerTest() { Expression <Func <int, int> > exp1 = (a) => 1 + a; var exp2 = ParameterReplacer.Replace <Func <int, int>, Expression <Func <int, int> > >(exp1, new Dictionary <string, object>() { { "a", 5 } }); exp2.Compile(); }
public static Expression <Func <T, bool> > And <T>(this Expression <Func <T, bool> > one, Expression <Func <T, bool> > another) { var candidateExpr = Expression.Parameter(typeof(T), "candidate"); var parameterReplacer = new ParameterReplacer(candidateExpr); var left = parameterReplacer.Replace(one.Body); var right = parameterReplacer.Replace(another.Body); var body = Expression.And(left, right); return(Expression.Lambda <Func <T, bool> >(body, candidateExpr)); }
public static Expression <Func <TDestination, TValue> > ReplaceParameter <TSource, TDestination, TValue> (this Expression <Func <TSource, TValue> > expression, Expression <Func <TDestination, TSource> > toExtendWith) { var replacer = new ParameterReplacer(expression.Parameters.First(), toExtendWith.Body); var newBody = replacer.Visit(expression.Body); var newLambda = Expression.Lambda(newBody, toExtendWith.Parameters.First()); return((Expression <Func <TDestination, TValue> >)newLambda); }
public static Expression <Func <T, bool> > Or <T>(this Expression <Func <T, bool> > exp_left, Expression <Func <T, bool> > exp_right) { var candidateExpr = Expression.Parameter(typeof(T), "candidate"); var parameterReplacer = new ParameterReplacer(candidateExpr); var left = parameterReplacer.Replace(exp_left.Body); var right = parameterReplacer.Replace(exp_right.Body); var body = Expression.Or(left, right); return(Expression.Lambda <Func <T, bool> >(body, candidateExpr)); }
public override Expression <Func <T, bool> > ToExpression() { var specExpression = _spec.ToExpression(); var paramExpr = Expression.Parameter(typeof(T)); var exprBody = Expression.Not(specExpression.Body); var visitedExpr = new ParameterReplacer(paramExpr).Visit(exprBody); var finalExpr = Expression.Lambda <Func <T, bool> >(visitedExpr, paramExpr); return(finalExpr); }
/// <summary> /// 连接表达式或运算 /// </summary> /// <typeparam name="T">参数</typeparam> /// <param name="one">原表达式</param> /// <param name="another">新表达式</param> /// <returns></returns> public static Expression <Func <T, bool> > Or <T>(this Expression <Func <T, bool> > one, Expression <Func <T, bool> > another) { //创建新参数 var newParameter = Expression.Parameter(typeof(T), "parameter"); var parameterReplacer = new ParameterReplacer(newParameter); var left = parameterReplacer.Replace(one.Body); var right = parameterReplacer.Replace(another.Body); var body = Expression.Or(left, right); return(Expression.Lambda <Func <T, bool> >(body, newParameter)); }
/// <summary> /// Creates and returns an implication expression P ⇒ Q. /// As per the definition of implication, <code>Implies(model => model.P, model => model.Q)</code> is exactly equivalent to (though hopefully easier to read than) /// <code> /// model => !model.P || model.Q /// </code> /// </summary> /// <param name="p">The antecedent expression.</param> /// <param name="q">The consequent expression.</param> /// <returns>An implication expression.</returns> public static Expression <Predicate <TModel> > Implies(Expression <Predicate <TModel> > p, Expression <Predicate <TModel> > q) { // We essentially want !p.Body || q.Body, but with the parameter expressions in each replaced with a new singular one. // That's what ParameterReplacer does for us. Note that the name of the parameter from the first is used. Should we // complain if the name of the parameter in the second is different? Seems overkill.. var pr = new ParameterReplacer(p.Parameters[0].Name); return(Expression.Lambda <Predicate <TModel> >( Expression.OrElse( Expression.IsFalse(pr.VisitLambdaBody(p)), pr.VisitLambdaBody(q)), pr.NewParameter)); }
private static Expression <Func <T, bool> > Wrap <T>(Expression <Func <T, string> > accessor) { var stringContains = typeof(String).GetMethod("Contains", new[] { typeof(String) }); var pe = Expression.Parameter(typeof(T), "__x4326"); var newBody = new ParameterReplacer(pe).Visit(accessor.Body); var call = Expression.Call( newBody, stringContains, Expression.Constant("foo") ); return(Expression.Lambda <Func <T, bool> >(call, pe)); }
public void GetTypeToUseTest() { Expression <Func <Person, int> > p1 = p => p.Id; Expression <Func <Person, int> > p2 = p => 23; Expression <Func <Person, string> > p3 = p => "fdhtfghty"; p2 = ParameterReplacer.Replace(p2, p2.Parameters[0], p1.Parameters[0]) as Expression <Func <Person, int> >; p3 = ParameterReplacer.Replace(p3, p3.Parameters[0], p1.Parameters[0]) as Expression <Func <Person, string> >; //var func = RelationshipComparer<Person, Person>.CreateHashCodeOld<Person>(new List<Expression> { p1, p2, p3 }, p1.Parameters[0]); // var func = KeyComparer<Person>.CreateGetHashCodeFunc<Person>(new List<LambdaExpression> { p1, p2, p3 }); }
public static Expression <Func <T, Boolean> > Simplify <T>(this Expression expression) { if (expression == null) { return(null); } var parameters = Expression.Parameter(typeof(T)); var body = new ParameterReplacer(parameters).Visit(expression) ?? expression; var simplified = body is Expression <Func <T, Boolean> > lambda ? lambda : Expression.Lambda <Func <T, Boolean> >(body, parameters); return(simplified); }
public static Expression ReplaceParameter(Expression exp, ParameterExpression replace, ParameterExpression withThis) { var pr = new ParameterReplacer(replace, withThis); return pr.Visit(exp); }