EF扩展方法,方便动态查询

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace EFDemo
{
    /// <summary>
    /// Defines the <see cref="QueryExtention" />.
    /// </summary>
    public static class QueryExtention
    {
        /// <summary>
        /// The Where.
        /// </summary>
        /// <typeparam name="T">.</typeparam>
        /// <param name="source">The source<see cref="IQueryable{T}"/>.</param>
        /// <param name="whereConditions">The whereConditions<see cref="List{WhereCondition}"/>.</param>
        /// <returns>The <see cref="IQueryable{T}"/>.</returns>
        public static IQueryable<T> Where<T>(this IQueryable<T> source, List<WhereCondition> whereConditions) where T : class
        {
            foreach (var query in whereConditions)
            {
                source = source.Where(query.Filters.AsExpression<T>(query.Link));
            }
            return source;
        }
    }

    /// <summary>
    /// Defines the Operators.
    /// </summary>
    public enum Operators
    {
        /// <summary>
        /// Defines the None.
        /// </summary>
        None = 0,

        /// <summary>
        /// Defines the Equal.
        /// </summary>
        Equal = 1,

        /// <summary>
        /// Defines the Contains.
        /// </summary>
        Contains = 2,

        /// <summary>
        /// Defines the StartWith.
        /// </summary>
        StartWith = 3,

        /// <summary>
        /// Defines the EndWidth.
        /// </summary>
        EndWidth = 4,

        /// <summary>
        /// Defines the Range.
        /// </summary>
        Range = 5,

        /// <summary>
        /// Defines the GreaterThan.
        /// </summary>
        GreaterThan = 6,

        /// <summary>
        /// Defines the GreaterThanOrEqual.
        /// </summary>
        GreaterThanOrEqual = 7,

        /// <summary>
        /// Defines the LessThan.
        /// </summary>
        LessThan = 8,

        /// <summary>
        /// Defines the LessThanOrEqual.
        /// </summary>
        LessThanOrEqual = 9,
    }

    /// <summary>
    /// Defines the ConditionLink.
    /// </summary>
    public enum ConditionLink
    {
        /// <summary>
        /// Defines the OrElse.
        /// </summary>
        OrElse = 1,

        /// <summary>
        /// Defines the AndAlso.
        /// </summary>
        AndAlso = 2
    }

    /// <summary>
    /// Defines the <see cref="Query" />.
    /// </summary>
    public class Query
    {
        /// <summary>
        /// Gets or sets the Name.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the Operator.
        /// </summary>
        public Operators Operator { get; set; }

        /// <summary>
        /// Gets or sets the Value.
        /// </summary>
        public object Value { get; set; }

        /// <summary>
        /// Gets or sets the ValueMin.
        /// </summary>
        public object ValueMin { get; set; }

        /// <summary>
        /// Gets or sets the ValueMax.
        /// </summary>
        public object ValueMax { get; set; }
    }

    /// <summary>
    /// Defines the <see cref="QueryCollection" />.
    /// </summary>
    public class QueryCollection : Collection<Query>
    {
        /// <summary>
        /// The AsExpression.
        /// </summary>
        /// <typeparam name="T">.</typeparam>
        /// <param name="condition">The condition<see cref="ConditionLink?"/>.</param>
        /// <returns>The <see cref="Expression{Func{T, bool}}"/>.</returns>
        public Expression<Func<T, bool>> AsExpression<T>(ConditionLink? condition = ConditionLink.OrElse) where T : class
        {
            Type targetType = typeof(T);
            TypeInfo typeInfo = targetType.GetTypeInfo();
            var parameter = Expression.Parameter(targetType, "m");
            Expression expression = null;
            Func<Expression, Expression, Expression> Append = (exp1, exp2) =>
            {
                if (exp1 == null)
                {
                    return exp2;
                }
                return (condition ?? ConditionLink.OrElse) == ConditionLink.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2);
            };
            foreach (var item in this)
            {
                var property = typeInfo.GetProperty(item.Name);
                if (property == null ||
                    !property.CanRead ||
                    (item.Operator != Operators.Range && item.Value == null) ||
                    (item.Operator == Operators.Range && item.ValueMin == null && item.ValueMax == null))
                {
                    continue;
                }
                Type realType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
                if (item.Value != null)
                {
                    item.Value = Convert.ChangeType(item.Value, realType);
                }
                Expression<Func<object>> valueLamba = () => item.Value;
                switch (item.Operator)
                {
                    case Operators.Equal:
                        {
                            expression = Append(expression, Expression.Equal(Expression.Property(parameter, item.Name),
                                Expression.Convert(valueLamba.Body, property.PropertyType)));
                            break;
                        }
                    case Operators.GreaterThan:
                        {
                            expression = Append(expression, Expression.GreaterThan(Expression.Property(parameter, item.Name),
                                Expression.Convert(valueLamba.Body, property.PropertyType)));
                            break;
                        }
                    case Operators.GreaterThanOrEqual:
                        {
                            expression = Append(expression, Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name),
                                Expression.Convert(valueLamba.Body, property.PropertyType)));
                            break;
                        }
                    case Operators.LessThan:
                        {
                            expression = Append(expression, Expression.LessThan(Expression.Property(parameter, item.Name),
                                Expression.Convert(valueLamba.Body, property.PropertyType)));
                            break;
                        }
                    case Operators.LessThanOrEqual:
                        {
                            expression = Append(expression, Expression.LessThanOrEqual(Expression.Property(parameter, item.Name),
                                Expression.Convert(valueLamba.Body, property.PropertyType)));
                            break;
                        }
                    case Operators.Contains:
                        {
                            //var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
                            var contains = Expression.Call(Expression.Property(parameter, item.Name), "Contains", null,
                                Expression.Convert(valueLamba.Body, property.PropertyType));
                            //expression = Append(expression, Expression.AndAlso(nullCheck, contains));
                            expression = Append(expression, contains);
                            break;
                        }
                    case Operators.StartWith:
                        {
                            //var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
                            var startsWith = Expression.Call(Expression.Property(parameter, item.Name), "StartsWith", null,
                                Expression.Convert(valueLamba.Body, property.PropertyType));
                            expression = Append(expression, startsWith);
                            break;
                        }
                    case Operators.EndWidth:
                        {
                            //var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
                            var endsWith = Expression.Call(Expression.Property(parameter, item.Name), "EndsWith", null,
                                Expression.Convert(valueLamba.Body, property.PropertyType));
                            expression = Append(expression, endsWith);
                            break;
                        }
                    case Operators.Range:
                        {
                            Expression minExp = null, maxExp = null;
                            if (item.ValueMin != null)
                            {
                                var minValue = Convert.ChangeType(item.ValueMin, realType);
                                Expression<Func<object>> minValueLamda = () => minValue;
                                minExp = Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(minValueLamda.Body, property.PropertyType));
                            }
                            if (item.ValueMax != null)
                            {
                                var maxValue = Convert.ChangeType(item.ValueMax, realType);
                                Expression<Func<object>> maxValueLamda = () => maxValue;
                                maxExp = Expression.LessThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(maxValueLamda.Body, property.PropertyType));
                            }

                            if (minExp != null && maxExp != null)
                            {
                                expression = Append(expression, Expression.AndAlso(minExp, maxExp));
                            }
                            else if (minExp != null)
                            {
                                expression = Append(expression, minExp);
                            }
                            else if (maxExp != null)
                            {
                                expression = Append(expression, maxExp);
                            }

                            break;
                        }
                }
            }
            if (expression == null)
            {
                return null;
            }
            return ((Expression<Func<T, bool>>)Expression.Lambda(expression, parameter));
        }
    }

    /// <summary>
    /// Defines the <see cref="WhereCondition" />.
    /// </summary>
    public class WhereCondition
    {
        /// <summary>
        /// Gets or sets the Filters.
        /// </summary>
        public QueryCollection Filters { get; set; }

        /// <summary>
        /// Gets or sets the Link.
        /// </summary>
        public ConditionLink Link { get; set; } = ConditionLink.OrElse;
    }
}

 

上一篇:一、获取EF


下一篇:EF应用