Exemplo n.º 1
0
        protected override Expression VisitBinary(BinaryExpression node)
        {
            using var mc = log?.Enter(LogLevel.LinqExpression, node);

            if (ExpressionTreeHelpers.SupportedComparisons.ContainsKey(node.NodeType))
            {
                foreach (var prop in TypeProperties)
                {
                    if (ExpressionTreeHelpers.IsMatchingMemberValueExpression(node, typeof(T), prop.Name))
                    {
                        object testValue = TranslateValue(prop, ExpressionTreeHelpers.GetValueFromExpression(node, typeof(T), prop.Name));
                        AddClause($"[{TranslateFieldName(prop)}] {ExpressionTreeHelpers.SupportedComparisons[node.NodeType]} '{testValue}' ");
                        return(node);
                    }
                }

                if (node.Left.NodeType == ExpressionType.Call)
                {
                    object testValue = TranslateValue(null, ExpressionTreeHelpers.GetValueFromExpression(node.Right));
                    futureComparisons.Push($"{ExpressionTreeHelpers.SupportedComparisons[node.NodeType]} '{testValue}'");
                }

                return(base.VisitBinary(node));
            }
            else if (node.NodeType == ExpressionType.OrElse || node.NodeType == ExpressionType.Or)
            {
                log?.WriteLine(LogLevel.LinqQuery, $"\t[{node.NodeType}]: {node.Left.NodeType} vs. {node.Right.NodeType}");

                AddClause("(");
                base.Visit(node.Left);
                AddClause(" OR ");
                base.Visit(node.Right);
                AddClause(")");

                return(node);
            }
            else if (node.NodeType == ExpressionType.AndAlso || node.NodeType == ExpressionType.And)
            {
                log?.WriteLine(LogLevel.LinqQuery, $"\t[{node.NodeType}]: {node.Left.NodeType} vs. {node.Right.NodeType}");

                AddClause("(");
                base.Visit(node.Left);
                AddClause(" AND ");
                base.Visit(node.Right);
                AddClause(")");

                return(node);
            }
            else
            {
                log?.WriteLine(LogLevel.LinqQuery, $"ERROR: unsupported comparison: {node.NodeType}");
                return(base.VisitBinary(node));
            }
        }
Exemplo n.º 2
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            string prefix = (futureComparisons.TryPop(out string literalCompare) && literalCompare == "= 'False'") ? "NOT " : "";

            using var mc = log?.Enter(LogLevel.LinqExpression, node);

            // member.Contains(...) || member.StartsWith(...)
            if (node.Method.DeclaringType == typeof(string) && (node.Method.Name == nameof(string.StartsWith) ||
                                                                node.Method.Name == nameof(string.Contains)))
            {
                foreach (var prop in TypeProperties.Where(prop => prop.PropertyType == typeof(string)))
                {
                    if (ExpressionTreeHelpers.IsSpecificMemberExpression(node.Object, typeof(T), prop.Name))
                    {
                        object testValue = TranslateValue(prop, ExpressionTreeHelpers.GetValueFromExpression(node.Arguments[0]));
                        AddClause($"{prefix}[{TranslateFieldName(prop)}] CONTAINS '{testValue}' ");
                        return(node);
                    }
                }
            }
            // array.Contains(member) || List<string>.Contains(member)
            else if (node.Method.Name == nameof(string.Contains))
            {
                PropertyInfo propertyInfo     = null;
                Expression   valuesExpression = null;

                if (node.Method.DeclaringType == typeof(Enumerable))
                {
                    foreach (var prop in TypeProperties)
                    {
                        if (ExpressionTreeHelpers.IsSpecificMemberExpression(node.Arguments[0], typeof(T), prop.Name))
                        {
                            propertyInfo     = prop;
                            valuesExpression = node.Arguments[1];
                            break;
                        }
                        else if (ExpressionTreeHelpers.IsSpecificMemberExpression(node.Arguments[1], typeof(T), prop.Name))
                        {
                            propertyInfo     = prop;
                            valuesExpression = node.Arguments[0];
                            break;
                        }
                    }
                }
                else if (node.Method.DeclaringType == typeof(List <string>))
                {
                    foreach (var prop in TypeProperties)
                    {
                        if (ExpressionTreeHelpers.IsSpecificMemberExpression(node.Arguments[0], typeof(T), prop.Name))
                        {
                            propertyInfo     = prop;
                            valuesExpression = node.Object;
                            break;
                        }
                        if (ExpressionTreeHelpers.IsSpecificMemberExpression(node.Object, typeof(T), prop.Name))
                        {
                            propertyInfo     = prop;
                            valuesExpression = node.Arguments[0];
                            break;
                        }
                    }
                }
                else
                {
                    throw new Exception($"{node.Method.DeclaringType} must be Enumerable or List<string> to use 'Contains'");
                }

                if (valuesExpression == null || valuesExpression.NodeType != ExpressionType.Constant)
                {
                    throw new Exception($"'Contains' expression must compare to a set of literals - {valuesExpression?.NodeType}");
                }

                ConstantExpression ce = (ConstantExpression)valuesExpression;

                if (ce.Value is string text) // single value
                {
                    AddClause($"{prefix}[{TranslateFieldName(propertyInfo)}] CONTAINS '{ce.Value}' ");
                }
                else
                {
                    // Add each string in the collection to the list of locations to obtain data about.
                    var textValues = (IEnumerable <string>)ce.Value;
                    AddClause($"{prefix}[{TranslateFieldName(propertyInfo)}] IN ({string.Join(',', textValues.Select(s => "'" + s + "'"))}) ");
                }

                return(node);
            }

            return(base.VisitMethodCall(node));
        }