Linq Expression管理AndAlso和OrElse之间的优先级

时间:2018-12-05 11:19:52

标签: c# linq lambda expressionvisitor

我在数据层中有一个动态过滤系统,可以创建一些表达式来获取数据。

我有一个查询对象,其中包含我的过滤模型,即:

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呢?

0 个答案:

没有答案