首页 新闻 会员 周边 捐助

[Lambda高阶应用]Expression<Func<PoFileModel, bool>>动态属性拼接方法

0
悬赏园豆:10 [已解决问题] 解决于 2017-04-18 15:52

首先,我有个List<PoFileModel> list = PoService.GetAll(t=>xxxxxx);

还有个返回Expression<Func<PoFileModel, bool>>对象的PermissionExpression方法。

public static class PredicateExtensions
    {
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> exprLeft,
            Expression<Func<T, bool>> exprRight)
        {
            var invokedExpr = Expression.Invoke(exprRight, exprLeft.Parameters);

            return Expression.Lambda<Func<T, bool>>(Expression.OrElse(exprLeft.Body, invokedExpr), exprLeft.Parameters);
        }

        public static Expression<Func<PoFileModel, bool>> PermissionExpression(this Expression<Func<PoFileModel, bool>> predicate, string value, Func<PoFileModel, string> fieldFunc)
        {
            if (!string.IsNullOrEmpty(value) && value.Contains(";"))
            {
                string[] items = value.Split(';');

                Expression<Func<PoFileModel, bool>> predicate1 = o => fieldFunc(o).Contains(items[0]);
                for (int i = 1; i < items.Length; i++)
                {
                    int j = i;
                    predicate1 = predicate1.Or(o => fieldFunc(o).Contains(items[j]));
                }

                predicate = predicate.Or(predicate1);
            }
            else
            {
                predicate = predicate.Or(o => fieldFunc(o).Contains(value));
            }

            return predicate;
        }
    }

这是方法调用:

IQueryable<PoFileModel> newList = list.AsQueryable();

Expression<Func<PoFileModel, bool>> predicate = i => 1 == 0;

if (groups.Any(t => t.Name == Groups.UniqloVendor.ToString()))
{
    predicate = PermissionExpression(predicate, user.VendorCode, o => o.VendorCode);
}
if (groups.Any(t => t.Name == Groups.UniqloBranchFactory.ToString()))
{
    predicate = PermissionExpression(predicate, user.BranchFactoryCode, o => o.BranchFactoryCode);
}
if (groups.Any(t => t.Name == Groups.UniqloManagementFactory.ToString()))
{
    predicate = PermissionExpression(predicate, user.ManagementFactoryCode, o => o.ManagementFactoryCode);
}

return newList.Where(predicate).ToList();

这里有个问题:

当这个list赋给newList对象前没有ToList等调用时,实际上它只是一个表达式(延时执行),也就是说,最终会到数据库执行查询。

一旦执行这个newList.Where(predicate).ToList()语句,它会报错,提示类似"无法识别fieldFunc"等错误。

当这个list赋给newList对象时调用了ToList方法,那么,数据已经在本地。执行这个newList.Where(predicate).ToList()语句,会返回正确结果。

我想要效果的是:

如何在PermissionExpression内部方法里根据fieldFunc生成动态属性的表达式?

VAllen的主页 VAllen | 初学一级 | 园豆:94
提问于:2017-04-18 10:04
< >
分享
最佳答案
0
public static class ExpressionExtensions
{
    public static IQueryable<T> WhereIf<T>(this IQueryable<T> list, Expression<Func<T, bool>> expr)
    {
        if (expr == null)
        {
            return list;
        }

        return list.Where(expr);
    }

    public static Expression<Func<T, bool>> OrContains<T>(this Expression<Func<T, string>> fieldFunc, string value)
    {
        ParameterExpression parameter = fieldFunc.Parameters.First();
        MemberExpression member = fieldFunc.Body as MemberExpression;

        MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });

        Expression exprLeft;
        if (!string.IsNullOrEmpty(value) && value.Contains(";"))
        {
            var items = value.Split(';');

            exprLeft = null;
            foreach (var item in items)
            {
                ConstantExpression constant = Expression.Constant(item, typeof(string));
                MethodCallExpression exprRight = Expression.Call(member, method, constant);
                if (exprLeft == null)
                {
                    exprLeft = exprRight;
                }
                else
                {
                    exprLeft = Expression.Or(exprLeft, exprRight);
                }
            }

            if (exprLeft == null)
            {
                Expression<Func<T, bool>> defaultFilter = o => true;
                exprLeft = defaultFilter;
            }
        }
        else
        {
            ConstantExpression constant = Expression.Constant(value, typeof(string));
            exprLeft = Expression.Call(member, method, constant);
        }

        Expression<Func<T, bool>> expr = Expression.Lambda<Func<T, bool>>(exprLeft, parameter);

        return expr;
    }

    public static Expression<Func<T, bool>> OrContainsIf<T>(this Expression<Func<T, bool>> expr, Expression<Func<T, string>> fieldFunc, string value)
    {
        if (expr == null)
        {
            expr = OrContains(fieldFunc, value);
        }
        else
        {
            expr = expr.Or(OrContains(fieldFunc, value));
        }

        return expr;
    }
}
Expression<Func<PoFileModel, bool>> expr = null;
if (groups.Any(t => t.Name == Groups.UniqloAdmin.ToString()))
{
    expr = expr.OrContainsIf(o => o.VendorCode, user.VendorCode);
    expr = expr.OrContainsIf(o => o.BranchFactoryCode, user.BranchFactoryCode);
    expr = expr.OrContainsIf(o => o.ManagementFactoryCode, user.ManagementFactoryCode);
}
else
{
    if (groups.Any(t => t.Name == Groups.UniqloVendor.ToString()))
    {
        expr = expr.OrContainsIf(o => o.VendorCode, user.VendorCode);
    }
    if (groups.Any(t => t.Name == Groups.UniqloBranchFactory.ToString()))
    {
        expr = expr.OrContainsIf(o => o.BranchFactoryCode, user.BranchFactoryCode);
    }
    if (groups.Any(t => t.Name == Groups.UniqloManagementFactory.ToString()))
    {
        expr = expr.OrContainsIf(o => o.ManagementFactoryCode, user.ManagementFactoryCode);
    }
}

return list.WhereIf(expr).ToList();

已自己解决。

VAllen | 初学一级 |园豆:94 | 2017-04-18 15:52
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册