示例#1
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));
        }