Имеется модель EF
public class OrderDbModel
{
public bool IsPayed { get; set; }
public string Name { get; set; }
public DateTime Created { get; set; }
public bool IsDeleted { get; set; }
}
Ей соответствует доменная модель:
public class Order
{
public bool IsPayed { get; set; }
public string Name { get; set; }
}
Чтобы получить список доменных моделей заказов из сервиса в слое бизнес-логики приложения, предполагается использование следующего класса-фильтра
public class OrderFilter
{
public bool GetUnpayed { get; set; }
public IEnumerable
Для получения списка доменных моделей по фильтру создан сервис, который использует репозиторий:
public class OrderService
{
private readonly IOrderRepository _repository;
public OrderService(IOrderRepository repository)
{
_repository = repository;
}
public IEnumerable
var orders = _repository.Get(filterExpression);
return Mapper.Map
Собственно, сам вопрос - в комментариях в коде сервиса. Не получается динамически сформировать filterExpression. Крайне интересен пример кода для данного конкретного случая с подробным описанием. Имеются ли какие-то библиотеки, которые позволяют это сделать с наименьшими трудозатратами?
PS: .NET Framework 4.6, C# 6.
Пример значений:
для OrderFilter со значениями { GetUnpayed = false, Names = new List
Ответ
И так, вам нужен способ комбинировать выражения. Проще всего это сделать через операцию бета-редукции (т.е. подстановки фактического параметра на место формального).
Для этого понадобится вот такой простейший визитор (visitor, "посетитель"):
class Reducer : ExpressionVisitor
{
private readonly IDictionary
public Reducer(IDictionary
protected override Expression VisitParameter(ParameterExpression node)
{
Expression result;
if (arguments.TryGetValue(node, out result))
return result;
return base.VisitParameter(node);
}
}
Даже если вы не сталкивались с классом ExpressionVisitor ранее - тут все просто. Класс Reducer заменяет в выражении параметры (объекты класса ParameterExpression ) на соответствующие им во входном словаре, если находит их там. Остальные узлы выражения он не трогает.
Теперь можно определить операцию подстановки. Тут все просто: формируем словарь параметров и передаем его классу Reducer после чего прогоняем через Reducer тело лямбда-функции:
public static Expression BetaReduce(this LambdaExpression expr, params Expression[] args)
{
Debug.Assert(expr.Parameters.Count == args.Length);
var mapping = new Dictionary
public static Expression
Или комбинатор Or:
public static Expression
Теперь вам ничего не помешает сложить все ваши условия в список, после чего объединить их все через And:
var conditions = new List
if (filter.GetUnpayed)
conditions.Add(x => !x.IsPayed);
...
var filterExpression = ExpressionUtils.And(conditions);
Если же вам не нравится работать с выражениями в "сыром" виде, можете попробовать библиотеку LinqKit
Комментариев нет:
Отправить комментарий