C#, осуществляющий рефакторинг лямбда-выражения

Таблицы::

SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'

столбцы::

SELECT * FROM INFORMATION_SCHEMA.COLUMNS 

или

SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='your_table_name'
7
задан Toto 17 September 2009 в 13:34
поделиться

4 ответа

Я считаю, что более чистого способа сделать это в вашем случае нет. Вы можете использовать BinaryExpression , как вы упомянули. Вы можете инкапсулировать вызовы BinaryExpression и Expression.Lambda в метод и вызвать его вместо этого (например, PredicateBuilder.And ), но ни один из них не так чист, как текущий синтаксис IMO.

3
ответ дан 7 December 2019 в 03:18
поделиться

Проблема с лямбда-выражениями заключается в том, что они неизменяемы, и вы не можете легко заменить параметры лямбда. Моя первоначальная идея заключалась в том, чтобы сделать что-то вроде этого ( к сожалению, это не сработает ):

public static class ExpressionExtesions
{
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> baseCondition, Expression<Func<T, bool>> additionalCondition)
    {
        var and = Expression.AndAlso(baseCondition.Body, additionalCondition.Body);
        return Expression.Lambda<Func<T, bool>>(and, baseCondition.Parameters);  // additionalCondition.Body still uses its own parameters so this fails on Compile()
    }
}

и использовать в коде:

Expression<Func<User, bool>> e = usr => usr.IsActive && usr.Group != "PROCESS";

var e1 = e.And(u => u.Name != null);
var e2 = e.And(u => u.Name != "A");
var e3 = e.And(u => u.Name != "B");

Возможное решение

Вы можете попробовать использовать одно из проект, направленный на реализацию построителей выражений. Я не использовал ни одного из них, но Google дает много ссылок, например:

Другой подход

Если вы используете эти выражения в LINQ для фильтрации значений, вы можете использовать другой подход (не комбинировать выражения, а комбинировать фильтры):

var activeUsers = allUsers.Where(usr => usr.IsActive && usr.Group != "PROCESS");

var usersAll = activeUsers.Where(u => u.Name != null);
var usersNotA = activeUsers.Where(u => u.Name != "A");
var usersNotB = activeUsers.Where(u => u.Name != "B");
3
ответ дан 7 December 2019 в 03:18
поделиться
var test = new Func<User, bool>(u=> u.IsActive && u.Group != "PROCESS");
Expression<Func<User, bool>> e1 = (User u) => test(u) && u.Name != null;
Expression<Func<User, bool>> e2 = (User u) => test(u) && u.Name != "A";
Expression<Func<User, bool>> e3 = (User u) => test(u) && u.Name != "B";
1
ответ дан 7 December 2019 в 03:18
поделиться

Я не думаю, что обязательно есть лучший ответ, чем тот, который вы уже используете. Как упоминает Мердад, вам придется построить более глубокое дерево, используя BinaryExpression, и я думаю, что это будет шагом назад в удобочитаемости вашего текущего кода.

В зависимости от вашего использования вы можете иметь возможность чтобы сэкономить несколько строк кода, используя семантику закрытия и сделав что-то вроде этого:

string name = null;

Expression<Func<User, bool>> e = 
  (User u) => u.IsActive && u.Group != "PROCESS" && u.Name != name;

var expr = e.Compile();

name = "A";
var result = expr.Invoke(u); //True (assume u.Name = "B")

name = "B";
result = expr.Invoke(u); //False

... но будет ли это какое-либо использование, будет зависеть от того, что вы делаете со скомпилированным делегатом. Может быть для вас совершенно бесполезен, но стоит упомянуть на всякий случай!

2
ответ дан 7 December 2019 в 03:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: