Лямбда-выражения — это мощная функция C#, которая позволяет разработчикам создавать анонимные функции на лету. Они часто используются с запросами LINQ для предоставления краткого, удобочитаемого кода для обработки и фильтрации данных. Однако что, если вам нужно создать лямбда-выражение динамически на основе пользовательского ввода? В этом руководстве мы рассмотрим процесс создания динамических лямбда-выражений и их использования для фильтрации списка записей в C#.

Доступ к репозиторию GitHub: Ссылка

Шаг 1: Определение классов записи и фильтра

Прежде чем мы углубимся в динамические лямбда-выражения, давайте сначала определим два класса: Record и Filter. Класс Record представляет отдельную запись со свойствами Id, Name и Age, а класс Filter представляет условие фильтра со свойствами ColumnNameи Value.

class Record
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

class Filter
{
    public string ColumnName { get; set; }
    public string Value { get; set; }
}

Шаг 2: Создание выражения динамического фильтра

В методе Main мы создадим список объектов Record и список объектов Filter. Затем мы создадим выражение параметра для входных данных типа Record.

var data = new List<Record>
{
    new Record { Id = 1, Name = "Rashad", Age = 25 },
    new Record { Id = 2, Name = "Elvin", Age = 30 },
    new Record { Id = 3, Name = "Ceyhun", Age = 35 },
    new Record { Id = 4, Name = "Aysel", Age = 40 },
};

var filters = new List<Filter>
{
    new Filter { ColumnName = "Name", Value = "E" },
    new Filter { ColumnName = "Age", Value = "30" },
};

var parameter = Expression.Parameter(typeof(Record), "record");

Затем выполните цикл по каждому объекту Filter в filters и создайте выражение динамического фильтра на основе заданных условий фильтрации.

Expression filterExpression = null;
foreach (var filter in filters)
{
    var property = Expression.Property(parameter, filter.ColumnName);
    var constant = Expression.Constant(filter.Value);
    Expression comparison;

    if (property.Type == typeof(string))
    {
        comparison = Expression.Call(property, "Contains", Type.EmptyTypes, constant);
    }
    else
    {
        //Convert values based on property type
        constant = Expression.Constant(Convert.ToInt32(filter.Value));
        comparison = Expression.Equal(property, constant);
    }

    filterExpression = filterExpression == null
        ? comparison
        : Expression.And(filterExpression, comparison);
}

Важно! Нам необходимо преобразовать значения на основе типа свойства в foreachцикле.

Шаг 3: Создание и компиляция лямбда-выражения

Теперь создайте лямбда-выражение, используя выражение фильтра и выражение параметра. Скомпилируйте лямбда-выражение в делегат типа Func<Record, bool>.

var lambda = Expression.Lambda<Func<Record, bool>>(filterExpression, parameter);
var func = lambda.Compile();

Шаг 4. Фильтрация данных и отображение результатов

Наконец, используйте метод расширения Where из LINQ для фильтрации входных данных с помощью делегата. Выведите отфильтрованные записи на консоль.

var filteredData = data.Where(func);
foreach (var record in filteredData)
{
    Console.WriteLine($"Id: {record.Id}, Name: {record.Name}, Age: {record.Age}");
}

Заключение

В этом руководстве мы продемонстрировали, как создавать динамические лямбда-выражения на C# для фильтрации списка записей на основе определяемых пользователем условий фильтрации. Этот метод можно применять к любому набору свойств и условий, что делает его мощным инструментом для создания гибкой и многократно используемой логики фильтрации в ваших приложениях.

Репозиторий GitHub: Ссылка