Как мне составить существующие выражения Linq - PullRequest
11 голосов
/ 10 сентября 2008

Я хочу составить результаты двух выражений Linq. Они существуют в виде

Expression<Func<T, bool>>

Итак, два, которые я хочу составить, по сути являются делегатами для параметра (типа T), которые оба возвращают логическое значение. Результат, который я хотел бы составить, был бы логической оценкой логических значений. Я бы, вероятно, реализовал его как метод расширения, поэтому мой синтаксис будет выглядеть примерно так:

Expression<Func<User, bool>> expression1 = t => t.Name == "steve";
Expression<Func<User, bool>> expression2 = t => t.Age == 28;
Expression<Func<User, bool>> composedExpression = expression1.And(expression2);

А позже в своем коде я хочу оценить составленное выражение

var user = new User();
bool evaluated = composedExpression.Compile().Invoke(user);

Я возился с несколькими разными идеями, но боюсь, что это сложнее, чем я ожидал. Как это сделать?

Ответы [ 2 ]

16 голосов
/ 10 сентября 2008

Вот пример:

var user1 = new User {Name = "steve", Age = 28};
var user2 = new User {Name = "foobar", Age = 28};

Expression<Func<User, bool>> expression1 = t => t.Name == "steve";
Expression<Func<User, bool>> expression2 = t => t.Age == 28;

var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());

var result = Expression.Lambda<Func<User, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);

Console.WriteLine(result.Compile().Invoke(user1)); // true
Console.WriteLine(result.Compile().Invoke(user2)); // false

Вы можете повторно использовать этот код с помощью методов расширения:

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

public static class PredicateExtensions
{
  public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1,Expression<Func<T, bool>> expression2)
  {
    InvocationExpression invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());

    return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
  }
}

class Program
{
  static void Main(string[] args)
  {
    var user1 = new User {Name = "steve", Age = 28};
    var user2 = new User {Name = "foobar", Age = 28};

    Expression<Func<User, bool>> expression1 = t => t.Name == "steve";
    Expression<Func<User, bool>> expression2 = t => t.Age == 28;

    var result = expression1.And(expression2);

    Console.WriteLine(result.Compile().Invoke(user1));
    Console.WriteLine(result.Compile().Invoke(user2));
  }
}
5 голосов
/ 21 июля 2009

Вы также можете использовать LinqKit, который может сделать всю эту работу за вас. Посмотрите эту ссылку http://www.albahari.com/nutshell/linqkit.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...