예제 #1
0
        /// <summary>
        /// Creates a lambda expression, that checks a Document to satisfy the list of conditions.
        /// Then compiles it and returns a predicate.
        /// </summary>
        private static Func <Document, bool> CreatePredicate(SearchConditions conditions, Type entityType)
        {
            // parameter, that represents input Document
            var docParameter = Expression.Parameter(typeof(Document));

            Expression predicateExp = null;

            foreach (var condition in conditions.Flatten())
            {
                string fieldName = condition.Item1;

                var fieldPropertyInfo = entityType.GetProperty(fieldName);
                if (fieldPropertyInfo == null)
                {
                    throw new InvalidOperationException(string.Format("An entity type {0} doesn't contain a property with name {1}, which was specified in search condition", entityType.Name, fieldName));
                }

                var fieldType   = fieldPropertyInfo.PropertyType;
                var fieldValues = condition.Item2.Values;

                // operation of getting a Document property value by it's name
                Expression getFieldExp = Expression.Property(docParameter, "Item", Expression.Constant(fieldName));

                if (fieldType.BaseType == typeof(Enum))
                {
                    // need to convert enums to ints
                    getFieldExp = Expression.Convert(getFieldExp, typeof(int));
                }

                // operation of converting the property to fieldType
                var operand1 = Expression.Convert(getFieldExp, fieldType);

                Expression conditionExp;
                if (condition.Item2.Operator == ScanOperator.In)
                {
                    // special support for IN operator

                    var valueList = new ArrayList();
                    foreach (var fieldValue in fieldValues)
                    {
                        valueList.Add(fieldValue.ToObject(fieldType));
                    }

                    conditionExp = Expression.Call
                                   (
                        Expression.Constant(valueList),
                        "Contains",
                        new Type[0],
                        Expression.Convert(operand1, typeof(object))
                                   );
                }
                else
                {
                    Expression valueExp = Expression.Constant(fieldValues[0]);

                    if (fieldType.BaseType == typeof(Enum))
                    {
                        // need to convert enums to ints
                        valueExp = Expression.Convert(valueExp, typeof(int));
                    }

                    // operation of converting the fieldValue to fieldType
                    var operand2 = Expression.Convert(valueExp, fieldType);

                    // now getting a predicate for current field
                    conditionExp = ScanOperatorToExpression(condition.Item2.Operator, operand1, operand2);
                }

                // attaching it to other predicates
                predicateExp = predicateExp == null ? conditionExp : Expression.AndAlso(predicateExp, conditionExp);
            }

            Debug.Assert(predicateExp != null);
            // compiling the lambda into a predicate
            return((Func <Document, bool>)Expression.Lambda(predicateExp, docParameter).Compile());
        }
예제 #2
0
        /// <summary>
        /// Creates a lambda expression, that checks a Document to satisfy the list of conditions.
        /// Then compiles it and returns a predicate.
        /// </summary>
        private static Func<Document, bool> CreatePredicate(SearchConditions conditions, Type entityType)
        {
            // parameter, that represents input Document
            var docParameter = Expression.Parameter(typeof(Document));

            Expression predicateExp = null;

            foreach (var condition in conditions.Flatten())
            {
                string fieldName = condition.Item1;

                var fieldPropertyInfo = entityType.GetProperty(fieldName);
                if (fieldPropertyInfo == null)
                {
                    throw new InvalidOperationException(string.Format("An entity type {0} doesn't contain a property with name {1}, which was specified in search condition", entityType.Name, fieldName));
                }

                var fieldType = fieldPropertyInfo.PropertyType;
                var fieldValues = condition.Item2.Values;

                // operation of getting a Document property value by it's name 
                Expression getFieldExp = Expression.Property(docParameter, "Item", Expression.Constant(fieldName));

                if (fieldType.BaseType == typeof (Enum))
                {
                    // need to convert enums to ints
                    getFieldExp = Expression.Convert(getFieldExp, typeof (int));
                }

                // operation of converting the property to fieldType
                var operand1 = Expression.Convert(getFieldExp, fieldType);

                Expression conditionExp;
                if (condition.Item2.Operator == ScanOperator.In)
                {
                    // special support for IN operator

                    var valueList = new ArrayList();
                    foreach (var fieldValue in fieldValues)
                    {
                        valueList.Add(fieldValue.ToObject(fieldType));
                    }

                    conditionExp = Expression.Call
                        (
                            Expression.Constant(valueList), 
                            "Contains", 
                            new Type[0], 
                            Expression.Convert(operand1, typeof(object))
                        );
                }
                else
                {
                    Expression valueExp = Expression.Constant(fieldValues[0]);

                    if (fieldType.BaseType == typeof(Enum))
                    {
                        // need to convert enums to ints
                        valueExp = Expression.Convert(valueExp, typeof(int));
                    }

                    // operation of converting the fieldValue to fieldType
                    var operand2 = Expression.Convert(valueExp, fieldType);

                    // now getting a predicate for current field
                    conditionExp = ScanOperatorToExpression(condition.Item2.Operator, operand1, operand2);
                }

                // attaching it to other predicates
                predicateExp = predicateExp == null ? conditionExp : Expression.AndAlso(predicateExp, conditionExp);
            }

            Debug.Assert(predicateExp != null);
            // compiling the lambda into a predicate
            return (Func<Document, bool>)Expression.Lambda( predicateExp, docParameter ).Compile();
        }