private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter, IFunctionRegistry functionRegistry) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; double value = constant.Value; return(Expression.Constant(value, typeof(double))); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(Expression.Constant(constant.Value, typeof(double))); } else if (operation.GetType() == typeof(Variable)) { Variable variable = (Variable)operation; Func <string, FormulaContext, double> getVariableValueOrThrow = PrecompiledMethods.GetVariableValueOrThrow; return(Expression.Call(null, getVariableValueOrThrow.GetMethodInfo(), Expression.Constant(variable.Name), contextParameter)); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; Expression argument1 = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry); return(Expression.Multiply(argument1, argument2)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Add(argument1, argument2)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Subtract(argument1, argument2)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry); return(Expression.Divide(dividend, divisor)); } else if (operation.GetType() == typeof(Modulo)) { Modulo modulo = (Modulo)operation; Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry); return(Expression.Modulo(dividend, divisor)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; Expression @base = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry); Expression exponent = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry); return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent)); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; Expression argument = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry); return(Expression.Negate(argument)); } else if (operation.GetType() == typeof(And)) { And and = (And)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.And(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Or)) { Or and = (Or)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.Or(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessThan)) { LessThan lessThan = (LessThan)operation; Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessOrEqualThan)) { LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation; Expression argument1 = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterThan)) { GreaterThan greaterThan = (GreaterThan)operation; Expression argument1 = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterOrEqualThan)) { GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation; Expression argument1 = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Equal)) { Equal equal = (Equal)operation; Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.Equal(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(NotEqual)) { NotEqual notEqual = (NotEqual)operation; Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.NotEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); Type funcType; Type[] parameterTypes; Expression[] arguments; if (functionInfo.IsDynamicFunc) { funcType = typeof(DynamicFunc <double, double>); parameterTypes = new Type[] { typeof(double[]) }; Expression[] arrayArguments = new Expression[function.Arguments.Count]; for (int i = 0; i < function.Arguments.Count; i++) { arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } arguments = new Expression[1]; arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments); } else { funcType = GetFuncType(functionInfo.NumberOfParameters); parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters) select typeof(double)).ToArray(); arguments = new Expression[functionInfo.NumberOfParameters]; for (int i = 0; i < functionInfo.NumberOfParameters; i++) { arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } } Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry"); ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo)); Expression funcInstance; if (!functionInfo.IsOverWritable) { funcInstance = Expression.Convert( Expression.Property( Expression.Call( getFunctionRegistry, typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName)), "Function"), funcType); } else { funcInstance = Expression.Constant(functionInfo.Function, funcType); } return(Expression.Call( funcInstance, funcType.GetRuntimeMethod("Invoke", parameterTypes), arguments)); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
public void 根据条件_动态拼修改的字段() { DateTime cdate = DateTime.Now;; Expression <Func <Users, bool[]> > xxexp = p => new bool[] { p.UserName == "几十行....", p.Password == "bug制造者" , p.CreateTime == cdate, SM.Sql(p.Remark, "(select '奥德赛 终于改好了')") }; Expression <Func <Users, bool> >[] xxp = { p => p.UserName == p.UserName, p => p.Remark == p.Remark, }; var lambdap = Expression.Parameter(typeof(Users), "p"); //var lambdamod = Expression.MakeMemberAccess(Expression.Constant("测试12",typeof(string))); var leftmb = Expression.Property(lambdap, "UserName"); var rightmb = Expression.Property(Expression.Property(Expression.Constant(DateTime.Now), typeof(Users).GetProperty("UserName")), typeof(Users).GetProperty("UserName")); var eqexp = Expression.Equal(leftmb, rightmb); var lambdamod2 = Expression.MakeMemberAccess(Expression.Constant(DateTime.Now), typeof(Users).GetMember("CreateTime")[0]); var leftmb2 = Expression.MakeMemberAccess(lambdap, typeof(Users).GetMember("CreateTime")[0]); var rightmb2 = Expression.MakeMemberAccess(lambdamod2, typeof(Users).GetMember("CreateTime")[0]); var eqexp2 = Expression.Equal(leftmb2, rightmb2); var exparrss = NewArrayExpression.NewArrayInit(typeof(bool), eqexp, eqexp2); LambdaExpression lambdaExpr = Expression.Lambda(exparrss, new List <ParameterExpression>() { lambdap }); Console.WriteLine(lambdaExpr);// arg => (arg +1) var func = lambdaExpr.Compile() as Func <Users, bool[]>; var resu = func(new Users() { UserName = "******" }); //, new Users()); // ################ ////BinaryExpression. //var x = Expression.Equal(Expression.MakeMemberAccess(Expression.Variable(typeof(Users), "UserName"), typeof(Users).GetMember("UserName")[0]) // , Expression.MakeMemberAccess(Expression.Variable(typeof(Users), "UserName"), typeof(Users).GetMember("UserName")[0])); //LambdaExpression lambdaExpr = Expression.Lambda(Expression.Add(paramExpr, Expression.Constant(1)), new List<ParameterExpression>() { paramExpr }); //Console.WriteLine(lambdaExpr);// arg => (arg +1) //List <bool> edcolms = new List<bool>(); ////Expression.Constant(" "); // 常量表达式 //DateTime cdatec = DateTime.Now; //Users model = new Users() { UserName="******", CreateTime = cdate }; ////BinaryExpression.New() ////NewArrayExpression.New(typeof(Func<Users,bool>), ) //List<Expression> exparrxx = new List<Expression>(); ////exparrxx.Add(, )); //List<Expression<Func<Users, bool>>> exparr = new List<Expression<Func<Users, bool>>>(); //exparr.Add( p => p.UserName == model.UserName ); //exparr.Add( p => p.CreateTime == model.CreateTime ); //var arrexp = NewArrayExpression.NewArrayInit(typeof(bool), exparr); //var exparrs = Expression.NewArrayInit(typeof(bool), exparr); //LockDapperUtilsqlite<Users>.Update().EditColumn( ) // ########### //把editcolumn改为 where == 形式才能 随意拼接 }
private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter, IFunctionRegistry functionRegistry) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; return(Expression.Convert(Expression.Constant(constant.Value, typeof(int)), typeof(double))); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(Expression.Constant(constant.Value, typeof(double))); } else if (operation.GetType() == typeof(Variable)) { Type contextType = typeof(FormulaContext); Type dictionaryType = typeof(IDictionary <string, double>); Variable variable = (Variable)operation; Expression getVariables = Expression.Property(contextParameter, "Variables"); ParameterExpression value = Expression.Variable(typeof(double), "value"); Expression variableFound = Expression.Call(getVariables, dictionaryType.GetRuntimeMethod("TryGetValue", new Type[] { typeof(string), typeof(double).MakeByRefType() }), Expression.Constant(variable.Name), value); Expression throwException = Expression.Throw( Expression.New(typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(string.Format("The variable \"{0}\" used is not defined.", variable.Name)))); LabelTarget returnLabel = Expression.Label(typeof(double)); return(Expression.Block( new[] { value }, Expression.IfThenElse( variableFound, Expression.Return(returnLabel, value), throwException ), Expression.Label(returnLabel, Expression.Constant(0.0)) )); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; Expression argument1 = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry); return(Expression.Multiply(argument1, argument2)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Add(argument1, argument2)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Subtract(argument1, argument2)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry); return(Expression.Divide(dividend, divisor)); } else if (operation.GetType() == typeof(Modulo)) { Modulo modulo = (Modulo)operation; Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry); return(Expression.Modulo(dividend, divisor)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; Expression @base = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry); Expression exponent = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry); return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent)); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; Expression argument = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry); return(Expression.Negate(argument)); } else if (operation.GetType() == typeof(And)) { And and = (And)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.And(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Or)) { Or and = (Or)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.Or(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessThan)) { LessThan lessThan = (LessThan)operation; Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessOrEqualThan)) { LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation; Expression argument1 = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterThan)) { GreaterThan greaterThan = (GreaterThan)operation; Expression argument1 = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterOrEqualThan)) { GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation; Expression argument1 = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Equal)) { Equal equal = (Equal)operation; Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.Equal(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(NotEqual)) { NotEqual notEqual = (NotEqual)operation; Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.NotEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); Type funcType; Type[] parameterTypes; Expression[] arguments; if (functionInfo.IsDynamicFunc) { funcType = typeof(DynamicFunc <double, double>); parameterTypes = new Type[] { typeof(double[]) }; Expression[] arrayArguments = new Expression[function.Arguments.Count]; for (int i = 0; i < function.Arguments.Count; i++) { arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } arguments = new Expression[1]; arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments); } else { funcType = GetFuncType(functionInfo.NumberOfParameters); parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters) select typeof(double)).ToArray(); arguments = new Expression[functionInfo.NumberOfParameters]; for (int i = 0; i < functionInfo.NumberOfParameters; i++) { arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } } Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry"); ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo)); return(Expression.Block( new[] { functionInfoVariable }, Expression.Assign( functionInfoVariable, Expression.Call(getFunctionRegistry, typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName)) ), Expression.Call( Expression.Convert(Expression.Property(functionInfoVariable, "Function"), funcType), funcType.GetRuntimeMethod("Invoke", parameterTypes), arguments))); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }