我在数据层中有一个动态过滤系统,可以创建一些表达式来获取数据。
我有一个查询对象,其中包含我的过滤模型,即:
public class BookingPagerQuery : PagerQuery
{
public bool? IsAssignedToPlanningSlot { get; set; }
public IEnumerable<Guid> PlanningSlotIds { get; set; }
public bool MainInterventionOnly { get; set; }
public bool MainOperatorOnly { get; set; }
}
在检索方法中,我执行过滤过程:
// For all, not deleted and only current establissment
Expression<Func<BookingOperator, bool>> where = a => !a.Deleted && a.EstablishmentId == establishmentId;
// filtering by role
if (userIdentity.Roles.HasAnyFlag(Roles.Admin))
{
// Admin : no filter
}
else if (userIdentity.Roles.HasAnyFlag(BookingRoles.ProcessSentBookings))
{
// booking process granted = no draft from others but his draft
where = where.Combine(c => !new List<BookingState> { BookingState.Draft }.Contains(c.BookingState));
where = where.CombineOrElse(c => c.CreatedBy == userIdentity.Id);
}
else if (userIdentity.Roles.HasAnyFlag(Roles.Secretary))
{
// 1. All self created
// 2. All from his office or service
// 3. with or without operator
Secretary secretary = Context.Secretaries.First(x => x.Id == userIdentity.Id);
// 1. Tous ceux créé par elles même
where = where.Combine(a => a.CreatedBy == userIdentity.Id);
// 2. pour son office ou partnerEst.
if (secretary.OfficeId != null)
{
// Les chirurgiens de son office
IEnumerable<Guid> privateSurgeons = Context.PrivateSurgeons.Where(x => x.OfficeId == secretary.OfficeId).Select(x => x.Id);
where = where.CombineOrElse(x => x.OperatorId.HasValue && privateSurgeons.Contains(x.OperatorId.Value));
}
if (secretary.ServiceId != null)
{
// Les chirurgiens de son service
IEnumerable<Guid> serviceMembers = Context.ServiceMembers.Where(x => x.ServiceId == secretary.ServiceId).Select(x => x.Id);
where = where.CombineOrElse(x => x.OperatorId.HasValue && serviceMembers.Contains(x.OperatorId.Value));
}
}
else if (userIdentity.Roles.HasAnyFlag(Roles.Surgeon))
{
// All self created
where = where.Combine(a => a.CreatedBy == userIdentity.Id);
// All given by the secretary
where = where.CombineOrElse(a => a.OperatorId == userIdentity.Id);
}
if (query.MainInterventionOnly)
{
where = where.Combine(a => a.IsMainIntervention == true);
}
if (query.MainOperatorOnly)
{
where = where.Combine(x => !x.OperatorType.HasValue || x.OperatorType == OperatorType.Operator1);
}
这里是Combine和CombineOrElse的代码:
public static Expression<Func<T, bool>> Combine<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
ParameterExpression param = Expression.Parameter(typeof(T), "param");
Expression newFirst = new ReplaceVisitor(first.Parameters.First(), param).Visit(first.Body);
Expression newSecond = new ReplaceVisitor(second.Parameters.First(), param).Visit(second.Body);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(newFirst, newSecond), param);
}
public static Expression<Func<T, bool>> CombineOrElse<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
ParameterExpression param = Expression.Parameter(typeof(T), "param");
Expression newFirst = new ReplaceVisitor(first.Parameters.First(), param).Visit(first.Body);
Expression newSecond = new ReplaceVisitor(second.Parameters.First(), param).Visit(second.Body);
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(newFirst, newSecond), param);
}
我可以重新编写代码以删除所有CombineElse
并将其包含在Combine
中,但是系统会变大,并且过滤器的粒度也会越来越大,因此我需要创建Expression作为CombineIncludeOrElse:
Comine:A && B
CombineOrElse:A || B
CombineIncludeOrElse:A &&(B || C)
我也改名为AndAlso和OrElse的Combine and CombineOrElse
那么,在表达式中我如何在没有A的情况下检索B并将C注入OrElse呢?