简体   繁体   中英

How to pass List of Expression in linq Query

I want to make Generic Class for Pagination with Generic Search Parameters. I used reflection to get filter properties. It could be achieved using Expressions which i don't know much about. Any help wud be appreciated.

public IEnumerable<T> ModelPagination(F filters) <-- F class filter properties eg. Name, CNIC for search
        {
            Type C = Type.GetType("filters");
            PropertyInfo[] properties = C.GetProperties();

            foreach (PropertyInfo prop in properties)
            {
                 prop.Name;
            }

            return dbEntity.Where(x => ...... ).ToList(); <--- want to pass each property as lambda for something like x -> x.Name == filters.Name || filters.Name == Null 

        }

This will build lambda expression which will intersect the properties between the generic type T and the Filter class and compare them for equality, also each separate property pair is combined with AND condition.

public static IEnumerable<T> ModelPagination<T>(F filter) 
{
        // all properties which are in the fiter class also present in the generic type T
        var commonPropertyNames = filter
                .GetType()
                .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                .Select(x => x.Name)
                .Intersect(
                    typeof(T)
                    .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                    .Select(x => x.Name)
                );
        var argumentExpression = Expression.Parameter(typeof(T), "x");
        var filterConstantExpression = Expression.Constant(filter);

        // build the expression
        var expression = (BinaryExpression)null;
        foreach (var propertyName in commonPropertyNames)
        {
            var filterPropertyExpression = Expression.Property(filterConstantExpression, propertyName);

            var equalExpression = Expression.Equal(
                Expression.Property(argumentExpression, propertyName),
                filterPropertyExpression
            );

            var nullCheckExpression = Expression.Equal(
                filterPropertyExpression,
                Expression.Constant(null)
            );

            var orExpression = Expression.OrElse(equalExpression, nullCheckExpression);

            if (expression == null)
            {
                expression = orExpression;
            }
            else
            {
                expression = Expression.AndAlso(expression, orExpression);
            }
        }

        var lambda = Expression.Lambda<Func<T, bool>>(expression, argumentExpression);

        return dbContext.Entry<T>().Where(lambda).ToList();
    }

If you have type T like this { FirstName, LastName } and Filter class like this { FirstName } it will create the following expression

x => x.FirstName == filter.FirstName || filter.FirstName == null

If you have type T like this { FirstName, LastName } and Filter class like this { FirstName, LastName } it will create the following expression

x => (x.FirstName == filter.FirstName || filter.FirstName == null) 
     && (x.LastName == filter.LastName || filter.LastName == null)

This will do the job, but there is room for optimization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM