The StringTypesExpressionCreator class provides a robust solution for creating string comparison expressions for target string properties. In this blog post, we will delve into the intricate details of the class and the underlying logic that makes it an invaluable asset for developers working with complex data filtering scenarios.

internal sealed class StringTypesExpressionCreator : IExpressionCreator
{
    public List<Expression<Func<T, bool>>> CreateExpressions<T>
        (string searchValue, Expression<Func<T, object>> keySelector)
    {
        List<MemberExpression> stringMemberExpressions = 
            keySelector.Body.ExtractStringMemberExpressions();

        var stringExpressions = new List<Expression<Func<T, bool>>>();
        foreach (var stringMemberExpression in stringMemberExpressions)
        {
            List<string> properties = stringMemberExpression.GetPropertyChain();

            ParameterExpression parameterExpression = keySelector.Parameters.Single();

            Expression expression = parameterExpression;
            foreach (var property in properties)
            {
                expression = Expression.Property(expression, property);
            }

            bool conversionResult =
                stringMemberExpression.Type.TryChangeType(
                    searchValue, out dynamic stringSearchValue);

            if (!conversionResult)
            {
                continue;
            }

            MethodInfo containsMethodInfo = stringMemberExpression.Type.GetMethod
                ("Contains", new[] { stringMemberExpression.Type })!;

            ConstantExpression constantExpression = Expression.Constant
                (stringSearchValue, stringMemberExpression.Type);

            MethodCallExpression methodCallExpression = Expression.Call
                (expression, containsMethodInfo, constantExpression);

            Expression<Func<T, bool>> stringExpression = Expression.Lambda<Func<T, bool>>
                (methodCallExpression, parameterExpression);

            stringExpressions.Add(stringExpression);
        }

        return stringExpressions;
    }
}

The stages of the CreateExpressions method are as follows:

  1. Extracting String Member Expressions: The method starts by extracting all string member expressions from the provided keySelector using the ExtractStringMemberExpressions extension method.
  2. Iterating Over String Member Expressions: The class then iterates over each string member expression, retrieving the associated property chain.
  3. Building Property Access Chain: It constructs the property access chain within the expression, preparing it for further manipulation.
  4. Type Conversion: The method attempts to convert the provided searchValue to the type of the string member expression, using the TryChangeType method.
  5. Dynamic Method Invocation: It dynamically invokes the Contains method for the specific string type.
  6. Creating Expression: The final step involves creating a Lambda expression encapsulating the method call expression, resulting in an Expression<Func<T, bool>>.
  7. Aggregating Expressions: All generated expressions are added to the list, which is then returned as the method output.