Expression BuildExpr <T>(Rule r, ParameterExpression param) { Expression propExpression = null; Type propType = null; ExpressionType tBinary; if (string.IsNullOrEmpty(r.MemberName))//check is against the object itself { propExpression = param; propType = propExpression.Type; } else if (r.MemberName.Contains('.'))//Child property { String[] childProperties = r.MemberName.Split('.'); var property = typeof(T).GetProperty(childProperties[0]); var paramExp = Expression.Parameter(typeof(T), "SomeObject"); propExpression = Expression.PropertyOrField(param, childProperties[0]); for (int i = 1; i < childProperties.Length; i++) { var orig = property; property = property.PropertyType.GetProperty(childProperties[i]); if (property != null) { propExpression = Expression.PropertyOrField(propExpression, childProperties[i]); } } propType = propExpression.Type; } else//Property { propExpression = Expression.PropertyOrField(param, r.MemberName); propType = propExpression.Type; } // is the operator a known .NET operator? if (ExpressionType.TryParse(r.Operator, out tBinary)) { var right = this.StringToExpression(r.TargetValue, propType); return(Expression.MakeBinary(tBinary, propExpression, right)); } else if (r.Operator == "IsMatch") { return(Expression.Call( typeof(Regex).GetMethod("IsMatch", new[] { typeof(string), typeof(string), typeof(RegexOptions) }), propExpression, Expression.Constant(r.TargetValue, typeof(string)), Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions)) )); } else //Invoke a method on the Property { var inputs = r.Inputs.Select(x => x.GetType()).ToArray(); var methodInfo = propType.GetMethod(r.Operator, inputs); if (!methodInfo.IsGenericMethod) { inputs = null;//Only pass in type information to a Generic Method } var expressions = r.Inputs.Select(x => Expression.Constant(x)).ToArray(); return(Expression.Call(propExpression, r.Operator, inputs, expressions)); } }
public static Func <T, bool> ToFunc <T>(Rule r, bool useTryCatchForNulls = true) { return(ToExpression <T>(r, useTryCatchForNulls).Compile()); }
private static Expression BuildExpr(Type type, Rule rule, Expression param, bool useTryCatch = true) { Expression propExpression; Type propType; if (param.Type == typeof(object)) { param = Expression.TypeAs(param, type); } var drule = rule as DataRule; if (string.IsNullOrEmpty(rule.MemberName)) //check is against the object itself { propExpression = param; propType = propExpression.Type; } else if (drule != null) { if (type != typeof(System.Data.DataRow)) { throw new RulesException(" Bad rule"); } propExpression = GetDataRowField(param, drule.MemberName, drule.Type); propType = propExpression.Type; } else if (param.Type == typeof(XmlDocument) || param.Type.GetProperties().Count() == 0) { var expObjt = ExpressionFactory.GetExpressionObject(param.Type.ToString()); propExpression = expObjt.GetExpression(param, rule); propType = propExpression.Type; } else { propExpression = GetProperty(param, rule.MemberName); propType = propExpression.Type; } if (useTryCatch) { propExpression = Expression.TryCatch( Expression.Block(propExpression.Type, propExpression), Expression.Catch(typeof(NullReferenceException), Expression.Default(propExpression.Type)) ); } // is the operator a known .NET operator? ExpressionType tBinary; if (ExpressionType.TryParse(rule.Operator, out tBinary)) { Expression right; var txt = rule.TargetValue as string; if (txt != null && txt.StartsWith("*.")) { txt = txt.Substring(2); right = GetProperty(param, txt); } else { right = StringToExpression(rule.TargetValue, propType); } return(Expression.MakeBinary(tBinary, propExpression, right)); } switch (rule.Operator) { case "IsMatch": { var exprObj = ExpressionFactory.GetExpressionObject(param.Type.ToString()); if (exprObj != null) { Expression expMember = exprObj.GetExpression(param, rule); } return(Expression.Call( _miRegexIsMatch.Value, propExpression, Expression.Constant(rule.TargetValue, typeof(string)), Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions)) )); } case "IsInteger": return(Expression.Call( _miIntTryParse.Value, propExpression, Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Int")) )); case "IsSingle": return(Expression.Call( _miFloatTryParse.Value, propExpression, Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Float")) )); case "IsDouble": return(Expression.Call( _miDoubleTryParse.Value, propExpression, Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Double")) )); case "IsDecimal": return(Expression.Call( _miDecimalTryParse.Value, propExpression, Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Decimal")) )); default: break; } var enumrOperation = IsEnumerableOperator(rule.Operator); if (enumrOperation != null) { var elementType = ElementType(propType); var lambdaParam = Expression.Parameter(elementType, "lambdaParam"); return(rule.Rules?.Any() == true ? Expression.Call(enumrOperation.MakeGenericMethod(elementType), propExpression, Expression.Lambda( BuildNestedExpression(elementType, rule.Rules, lambdaParam, ExpressionType.AndAlso), lambdaParam) ) : Expression.Call(enumrOperation.MakeGenericMethod(elementType), propExpression)); } else //Invoke a method on the Property { var inputs = rule.Inputs.Select(x => x.GetType()).ToArray(); var methodInfo = propType.GetMethod(rule.Operator, inputs); List <Expression> expressions = new List <Expression>(); if (methodInfo == null) { methodInfo = propType.GetMethod(rule.Operator); if (methodInfo != null) { var parameters = methodInfo.GetParameters(); int i = 0; foreach (var item in rule.Inputs) { expressions.Add(MRE.StringToExpression(item, parameters[i].ParameterType)); i++; } } } else { expressions.AddRange(rule.Inputs.Select(Expression.Constant)); } if (methodInfo == null) { throw new RulesException($"'{rule.Operator}' is not a method of '{propType.Name}"); } if (!methodInfo.IsGenericMethod) { inputs = null; //Only pass in type information to a Generic Method } var callExpression = Expression.Call(propExpression, rule.Operator, inputs, expressions.ToArray()); if (useTryCatch) { return(Expression.TryCatch( Expression.Block(typeof(bool), callExpression), Expression.Catch(typeof(NullReferenceException), Expression.Constant(false)) )); } else { return(callExpression); } } }
public static Func <object, bool> ToFunc(Type type, Rule r) { return(ToExpression(type, r).Compile()); }
Expression BuildExpr <T>(Rule r, ParameterExpression OrderType) { Expression propertyOnOrder = null; Type propType = null; ExpressionType tBinary; if (string.IsNullOrEmpty(r.MemberName))//check is against the object itself { propertyOnOrder = OrderType; propType = propertyOnOrder.Type; } else if (r.MemberName.Contains('.'))//Child property { String[] childProperties = r.MemberName.Split('.'); var property = typeof(T).GetProperty(childProperties[0]); var paramExp = Expression.Parameter(typeof(T), "SomeObject"); propertyOnOrder = Expression.PropertyOrField(OrderType, childProperties[0]); for (int i = 1; i < childProperties.Length; i++) { var orig = property; property = property.PropertyType.GetProperty(childProperties[i]); if (property != null) { propertyOnOrder = Expression.PropertyOrField(propertyOnOrder, childProperties[i]); } } propType = propertyOnOrder.Type; } else//Property { propertyOnOrder = Expression.PropertyOrField(OrderType, r.MemberName); propType = propertyOnOrder.Type; } // is the operator a known .NET operator? if (ExpressionType.TryParse(r.Operator, out tBinary) || r.Operator == "Function") { //no repetition of error message,action or setter found Expression right = null; BinaryExpression binary = null; MethodCallExpression ErrorMessage = Expression.Call(OrderType, "AddMessage", null, new Expression[] { Expression.Constant(r.ErrorMessage) }); if (r.Operator != "Function") { right = this.StringToExpression(r.TargetValue, propType); binary = Expression.MakeBinary(tBinary, propertyOnOrder, right); } //function if (!string.IsNullOrEmpty(r.Function)) { // var firstexp = Expression.MakeBinary(tBinary, propertyOnOrder, right); Expression[] functionParams = new Expression[] { Expression.Constant(r.ErrorMessage) }; Expression FunctionCall = Expression.Call(OrderType, r.Function, null, r.Inputs.Select(x => Expression.Constant(x)).ToArray()); if (r.Operator == "Function") { //call functon and if the function returns false, set error message //Expression.IfThenElse(FunctionCall, Expression.Constant(true) return(Expression.Condition(FunctionCall, Expression.Constant(true), Expression.Block(ErrorMessage, Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Constant(true), Expression.Constant(true))))); } return(Expression.Block(Expression.IfThenElse(binary, FunctionCall, ErrorMessage), Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Condition(binary, binary, Expression.Not(binary)), binary) ));//need fix-u dont // } //setter else if (!string.IsNullOrEmpty(r.Setter)) { //no repetition of error message,action or setter found var prop1 = Expression.PropertyOrField(OrderType, r.Setter.Split('=')[0]); var prop2 = Expression.Constant(r.Setter.Split('=')[1]); return(Expression.Block(Expression.IfThenElse(binary, Expression.Assign(prop1, prop2), ErrorMessage), Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Condition(binary, binary, Expression.Not(binary)), binary) )); // } // else { return(Expression.Block(Expression.IfThen(Expression.Not(binary), ErrorMessage), Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Condition(binary, binary, Expression.Not(binary)), binary) )); //var ifthen = Expression.IfThen(Expression.Not(binary), ErrorMessage); //return Expression.Block(ifthen, binary); } } else if (r.Operator == "IsMatch") { var tester = Expression.Call( typeof(Regex).GetMethod("IsMatch", new[] { typeof(string), typeof(string), typeof(RegexOptions) }), propertyOnOrder, Expression.Constant(r.TargetValue, typeof(string)), Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions)) ); return(Expression.Block(Expression.IfThen(tester, Expression.Call(OrderType, "AddMessage", null, new Expression[] { Expression.Constant(r.MemberName) })), tester)); } else //Invoke a method on the Property { Type[] parameterTypes = r.Inputs.Select(x => x.GetType()).ToArray(); var methodInfo = propType.GetMethod(r.Operator, parameterTypes); if (!methodInfo.IsGenericMethod) { parameterTypes = null;//Only pass in type information to a Generic Method } Expression[] prametersAsArray = r.Inputs.Select(x => Expression.Constant(x)).ToArray(); var firstcall = Expression.Call(propertyOnOrder, r.Operator, parameterTypes, prametersAsArray); var message = Expression.Call(OrderType, "AddMessage", null, new Expression[] { Expression.Constant(r.MemberName) }); var ifthen = Expression.IfThen(Expression.Not(firstcall), message); return(Expression.Block(ifthen, firstcall)); } }
private static Expression BuildExpr(Type type, Rule r, Expression param) { Expression propExpression; Type propType; if (param.Type == typeof(object)) { param = Expression.TypeAs(param, type); } var drule = r as DataRule; if (string.IsNullOrEmpty(r.MemberName)) //check is against the object itself { propExpression = param; propType = propExpression.Type; } else if (drule != null) { if (type != typeof(System.Data.DataRow)) { throw new RulesException(" Bad rule"); } propExpression = GetDataRowField(param, drule.MemberName, drule.Type); propType = propExpression.Type; } else { propExpression = GetProperty(param, r.MemberName); propType = propExpression.Type; } propExpression = Expression.TryCatch( Expression.Block(propExpression.Type, propExpression), Expression.Catch(typeof(NullReferenceException), Expression.Default(propExpression.Type)) ); // is the operator a known .NET operator? ExpressionType tBinary; if (Enum.TryParse(r.Operator, out tBinary)) { var right = StringToExpression(r.TargetValue, propType); return(Expression.MakeBinary(tBinary, propExpression, right)); } if (r.Operator == "IsMatch") { return(Expression.Call( _miRegexIsMatch.Value, propExpression, Expression.Constant(r.TargetValue, typeof(string)), Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions)) )); } else //Invoke a method on the Property { var inputs = r.Inputs.Select(x => x.GetType()).ToArray(); var methods = propType.GetMethods(); var methodInfo = propType.GetMethod(r.Operator, inputs); if (!methodInfo.IsGenericMethod) { inputs = null;//Only pass in type information to a Generic Method } var expressions = r.Inputs.Select(Expression.Constant).ToArray(); return(Expression.TryCatch( Expression.Block(typeof(bool), Expression.Call(propExpression, r.Operator, inputs, expressions)), Expression.Catch(typeof(NullReferenceException), Expression.Constant(false)) )); } }