MST

星途 面试题库

面试题:C#表达式树在动态查询中的应用

假设你有一个包含多个属性的类,如Person类有Name、Age等属性。现在需要根据用户输入的条件,例如“Age > 30 && Name.Contains('John')”,使用表达式树动态构建LINQ查询表达式,实现对Person集合的筛选,并返回符合条件的结果。请编写完整代码实现这一功能。
43.5万 热度难度
编程语言C#

知识考点

AI 面试

面试题答案

一键面试
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class QueryBuilder
{
    public static IEnumerable<Person> FilterPersons(IEnumerable<Person> persons, string condition)
    {
        // 解析条件字符串为表达式树
        ParameterExpression parameter = Expression.Parameter(typeof(Person), "p");
        Expression body = ParseCondition(condition, parameter);

        // 创建Lambda表达式
        Expression<Func<Person, bool>> lambda = Expression.Lambda<Func<Person, bool>>(body, parameter);

        // 使用LINQ进行筛选
        return persons.AsQueryable().Where(lambda).ToList();
    }

    private static Expression ParseCondition(string condition, ParameterExpression parameter)
    {
        // 简单的解析,这里假设条件格式正确,并且只处理 && 连接符
        string[] parts = condition.Split("&&");
        Expression left = ParseSingleCondition(parts[0].Trim(), parameter);

        for (int i = 1; i < parts.Length; i++)
        {
            Expression right = ParseSingleCondition(parts[i].Trim(), parameter);
            left = Expression.AndAlso(left, right);
        }

        return left;
    }

    private static Expression ParseSingleCondition(string singleCondition, ParameterExpression parameter)
    {
        // 简单的解析,这里假设条件格式正确,并且只处理 > 和 Contains
        string[] parts = singleCondition.Split(new[] { '>', ' ' }, 2);
        string propertyName = parts[0].Trim();
        string value = parts[1].Trim();

        MemberExpression property = Expression.Property(parameter, propertyName);

        if (singleCondition.Contains(">"))
        {
            ConstantExpression constant = Expression.Constant(int.Parse(value));
            return Expression.GreaterThan(property, constant);
        }
        else if (singleCondition.Contains("Contains"))
        {
            MethodCallExpression containsCall = Expression.Call(
                property,
                typeof(string).GetMethod("Contains", new[] { typeof(string) }),
                Expression.Constant(value.Trim('\'', '"'))
            );
            return containsCall;
        }

        throw new NotSupportedException($"Unsupported condition: {singleCondition}");
    }
}

你可以这样使用:

class Program
{
    static void Main()
    {
        List<Person> people = new List<Person>
        {
            new Person { Name = "John Doe", Age = 35 },
            new Person { Name = "Jane Smith", Age = 28 },
            new Person { Name = "John Smith", Age = 40 }
        };

        string condition = "Age > 30 && Name.Contains('John')";
        IEnumerable<Person> result = QueryBuilder.FilterPersons(people, condition);

        foreach (var person in result)
        {
            Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
        }
    }
}

上述代码实现了根据用户输入的条件字符串,动态构建表达式树并进行LINQ查询筛选的功能。代码中QueryBuilder类负责解析条件字符串并构建表达式树,FilterPersons方法使用构建好的表达式树进行筛选。Main方法展示了如何使用这个功能。注意,这里的解析是非常简单的,实际应用中可能需要更健壮的解析逻辑来处理各种复杂情况。