Пример #1
0
        public static Expression CallStringContains(ExpressionData exp, Expression ep)
        {
            var type = typeof(string);
            var mi   = type.GetMethod("Contains");

            if (mi == null)
            {
                throw new InvalidOperationException();
            }

            return(Expression.Call(ep, mi, Expression.Constant(exp.Expression.Data, typeof(string))));
        }
Пример #2
0
        private static ConstantExpression BuildContains(ExpressionData exp, Expression ep)
        {
            Type dataType;

            switch (exp.Expression.DataType)
            {
            case DataType.Integer:
                dataType = typeof(int);
                break;

            case DataType.String:
                dataType = typeof(string);
                break;

            case DataType.Decimal:
                dataType = typeof(decimal);
                break;

            case DataType.Double:
                dataType = typeof(double);
                break;

            case DataType.Boolean:
                dataType = typeof(bool);
                break;

            case DataType.DateTime:
                dataType = typeof(DateTime);
                break;

            case DataType.Guid:
                dataType = typeof(Guid);
                break;

            case DataType.Enum:
                dataType = ep.Type;
                break;

            case DataType.Expression:
            case null:
                throw new InvalidOperationException();

            default:
                throw new ArgumentOutOfRangeException();
            }

            var generic   = typeof(IEnumerable <>).MakeGenericType(dataType);
            var data      = JsonConvert.SerializeObject(exp.Expression.Data);
            var typedData = JsonConvert.DeserializeObject(data, generic);

            return(Expression.Constant(typedData));
        }
Пример #3
0
        public static Expression CallContains(ExpressionData exp, Expression ep)
        {
            Expression property = BuildContains(exp, ep);

            var cType    = GetIEnumerable(property.Type);
            var elemType = cType.GetGenericArguments()[0];

            var action = (MethodInfo)
                         GetGenericMethod(typeof(Enumerable), Action.Contains.ToString(), new[] { elemType },
                                          new[] { cType, elemType }, BindingFlags.Static);

            property = Expression.Convert(property, cType);

            return(Expression.Call(action, property, ep));
        }
Пример #4
0
        private LambdaExpression BuildListCall(ExpressionData exp, Expression ep, string peParam)
        {
            var pi = ((MemberExpression)ep).Member as PropertyInfo;

            if (pi == null)
            {
                throw new InvalidOperationException();
            }

            var type     = pi.PropertyType.GenericTypeArguments[0];
            var pe       = Expression.Parameter(type, peParam);
            var json     = JsonConvert.SerializeObject(exp.Expression.Data);
            var criteria = JsonConvert.DeserializeObject <Filter>(json);
            var be       = BoolExpression(criteria, null, pe);
            var generic  = typeof(Func <,>).MakeGenericType(type, typeof(bool));

            return(Expression.Lambda(generic, be, pe));
        }
Пример #5
0
        private Expression CreateExpression(Expression parameterExpression, ExpressionData exp)
        {
            Expression ex;

            switch (exp.Type)
            {
            case ExpressionType.Condition:
                ex = BoolExpression(exp.Filter, null, parameterExpression);
                break;

            case ExpressionType.Expression:

                Expression ep;

                switch (exp.Expression.PropertyType)
                {
                case PropertyType.Value:
                case PropertyType.Collection:
                case PropertyType.Key:
                case PropertyType.BasicCollection:
                case PropertyType.StringContains:
                    ep = BuilderUtility.GetProperty(parameterExpression, exp.Expression.PropertyId);
                    break;

                case PropertyType.Method:
                    ep = BuilderUtility.CallMethod(parameterExpression, exp, _methods);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                ex = BuildExpression(ep, exp);

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(ex);
        }
Пример #6
0
        public static Expression CallMethod(
            Expression parameterExpression,
            ExpressionData exp,
            IDictionary <string, IMethod> methods)
        {
            if (!methods.ContainsKey(exp.Expression.PropertyId))
            {
                throw new InvalidOperationException("Unable to find method from method collection");
            }

            var instance = methods[exp.Expression.PropertyId];
            var type     = instance.GetType();
            var constant = Expression.Constant(instance, type);

            var mi = (MethodInfo)
                     GetGenericMethod(typeof(IMethod), "Evaluate", new[] { parameterExpression.Type },
                                      new[] { parameterExpression.Type }, BindingFlags.Instance);

            return(Expression.Call(constant, mi, parameterExpression));
        }
Пример #7
0
        public static ConstantExpression BuildConstantExpression(
            IDictionary <string, IToken> tokens,
            Expression property,
            ExpressionData exp,
            DataType dataType)
        {
            ConstantExpression ce;

            if (exp.Expression.Right == null && string.IsNullOrWhiteSpace(exp.Expression.Token))
            {
                if (Nullable.GetUnderlyingType(property.Type) != null || dataType == DataType.String)
                {
                    return(Expression.Constant(null));
                }

                throw new InvalidOperationException("Constant value or token is missing");
            }

            if (exp.Expression.Right != null && !string.IsNullOrWhiteSpace(exp.Expression.Token))
            {
                throw new InvalidOperationException("Must specify a constant value or token but not both");
            }

            if (!string.IsNullOrWhiteSpace(exp.Expression.Token) && !tokens.ContainsKey(exp.Expression.Token))
            {
                throw new InvalidOperationException("Unable to find token from token collection");
            }

            switch (dataType)
            {
            case DataType.Expression:
                throw new InvalidOperationException();

            case DataType.Integer:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ToInt32(exp.Expression.Right)
                            : tokens[exp.Expression.Token].Value <int>(), typeof(int));

                break;

            case DataType.String:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ToString(exp.Expression.Right)
                            : tokens[exp.Expression.Token].Value <string>(), typeof(string));

                break;

            case DataType.Decimal:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ToDecimal(exp.Expression.Right)
                            : tokens[exp.Expression.Token].Value <decimal>(), typeof(decimal));

                break;

            case DataType.Double:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ToDouble(exp.Expression.Right)
                            : tokens[exp.Expression.Token].Value <double>(), typeof(double));

                break;

            case DataType.Boolean:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ToBoolean(exp.Expression.Right)
                            : tokens[exp.Expression.Token].Value <bool>(), typeof(bool));

                break;

            case DataType.DateTime:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ToDateTime(exp.Expression.Right)
                            : tokens[exp.Expression.Token].Value <DateTime>(), typeof(DateTime));

                break;

            case DataType.Guid:

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Guid.Parse(Convert.ToString(exp.Expression.Right))
                            : Guid.Parse(tokens[exp.Expression.Token].Value <string>()), typeof(Guid));

                break;

            case DataType.Enum:

                var type     = Nullable.GetUnderlyingType(property.Type);
                var enumType = Enum.GetUnderlyingType(type ?? property.Type);

                ce = Expression.Constant(
                    exp.Expression.Right != null
                            ? Convert.ChangeType(exp.Expression.Right, enumType)
                            : Convert.ChangeType(tokens[exp.Expression.Token].Value <int>(), enumType));

                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(dataType), dataType, null);
            }

            return(ce);
        }
Пример #8
0
        private Expression BuildExpression(Expression ep, ExpressionData exp)
        {
            Expression ex;

            var dataType   = exp.Expression.Type;
            var ce         = BuilderUtility.BuildConstantExpression(_tokens, ep, exp, dataType);
            var memberType = BuilderUtility.GetDataType(exp.Expression.Type, ep);

            switch (exp.Expression.PropertyType)
            {
            case PropertyType.Value:
                break;

            case PropertyType.Collection:
            case PropertyType.BasicCollection:

                ep =
                    BuilderUtility.CallAction(
                        exp.Expression.Action, ep, BuildListCall(exp, ep, $"f{_peCounter}"));

                _peCounter++;

                break;

            case PropertyType.Key:

                if (exp.Expression.Action == Action.Compare)
                {
                    break;
                }

                if (exp.Expression.Action != Action.Contains)
                {
                    throw new NotSupportedException();
                }

                ep = BuilderUtility.CallContains(exp, ep);

                break;

            case PropertyType.Method:
                break;

            case PropertyType.StringContains:

                ep = BuilderUtility.CallStringContains(exp, ep);

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            switch (exp.Expression.Operator)
            {
            case Operator.Eq:
                ex = Expression.Equal(ep, Expression.Convert(ce, memberType));
                break;

            case Operator.Neq:
                ex = Expression.NotEqual(ep, Expression.Convert(ce, memberType));
                break;

            case Operator.Gt:
                ex = Expression.GreaterThan(ep, Expression.Convert(ce, memberType));
                break;

            case Operator.Gte:
                ex = Expression.GreaterThanOrEqual(ep, Expression.Convert(ce, memberType));
                break;

            case Operator.Lt:
                ex = Expression.LessThan(ep, Expression.Convert(ce, memberType));
                break;

            case Operator.Lte:
                ex = Expression.LessThanOrEqual(ep, Expression.Convert(ce, memberType));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(ex);
        }