/// <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()); }
/// <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(); }