1. 程式人生 > 實用技巧 >動態拼接Lambda表示式2

動態拼接Lambda表示式2

動態拼接Lambda表示式

新增類

    #region lambda expression 拼接方式1
    /// <summary>
    /// Expression表示式樹
    /// </summary>
    public class LambdaParameteRebinder : ExpressionVisitor
    {
        /// <summary>
        /// 存放表示式樹的引數的字典
        /// </summary>
        private readonly Dictionary<ParameterExpression, ParameterExpression> map;

        
/// <summary> /// 建構函式 /// </summary> /// <param name="map"></param> public LambdaParameteRebinder(Dictionary<ParameterExpression, ParameterExpression> map) { this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>(); }
/// <summary> /// 過載引數訪問的方法,訪問表示式樹引數,如果字典中包含,則取出 /// </summary> /// <param name="node">表示式樹引數</param> /// <returns></returns> protected override Expression VisitParameter(ParameterExpression node) { if (map.TryGetValue(node, out
ParameterExpression expression)) { node = expression; } return base.VisitParameter(node); } public static Expression ReplaceParameter(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) { return new LambdaParameteRebinder(map).Visit(exp); } } /// <summary> /// 表示式數的lambda引數的拼接擴充套件方法 /// </summary> public static class LambdaExtension { /// <summary> /// Expression表示式樹lambda引數拼接組合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="first"></param> /// <param name="second"></param> /// <param name="merge"></param> /// <returns></returns> public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge) { var parameterMap = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); var secondBody = LambdaParameteRebinder.ReplaceParameter(parameterMap, second.Body); return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters); } /// <summary> /// Expression表示式樹lambda引數拼接--false /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression<Func<T, bool>> False<T>() => f => false; /// <summary> /// Expression表示式樹lambda引數拼接-true /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression<Func<T, bool>> True<T>() => f => true; /// <summary> /// Expression表示式樹lambda引數拼接--and /// </summary> /// <typeparam name="T"></typeparam> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) => first.Compose(second, Expression.And); /// <summary> /// Expression表示式樹lambda引數拼接--or /// </summary> /// <typeparam name="T"></typeparam> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) => first.Compose(second, Expression.Or); } #endregion #region lambda expression 拼接方式2 /// <summary> /// 表示式數的lambda引數的拼接擴充套件方法擴充套件類 /// </summary> public class LambdaExpressionParameter : ExpressionVisitor { /// <summary> /// 表示式數的lambda引數 /// </summary> public ParameterExpression parameterExpression { get; private set; } /// <summary> /// 建構函式 /// </summary> /// <param name="parameterExpression"></param> public LambdaExpressionParameter(ParameterExpression parameterExpression) { this.parameterExpression = parameterExpression; } /// <summary> /// 替代方法 /// </summary> /// <param name="expression"></param> /// <returns></returns> public Expression Replace(Expression expression) { return base.Visit(expression); } /// <summary> /// 過載引數訪問的方法,處理引數表示式 /// </summary> /// <param name="node"></param> /// <returns></returns> protected override Expression VisitParameter(ParameterExpression node) { return this.parameterExpression; } } /// <summary> /// 表示式數的lambda引數的拼接擴充套件方法 /// </summary> public static class LambdaExpressionExtend { /// <summary> /// Expression表示式樹lambda引數拼接--and /// </summary> /// <typeparam name="T"></typeparam> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static Expression<Func<T, bool>> And1<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) { //var param = first.Parameters[0]; var param = Expression.Parameter(typeof(T), "w");//指定引數和引數名稱 LambdaExpressionParameter lambdaExpression = new LambdaExpressionParameter(param); var left = lambdaExpression.Replace(first.Body); var right = lambdaExpression.Replace(second.Body); var body = Expression.And(left, right); return Expression.Lambda<Func<T, bool>>(body, param); } /// <summary> /// Expression表示式樹lambda引數拼接--or /// </summary> /// <typeparam name="T"></typeparam> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static Expression<Func<T, bool>> Or1<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) { //var param = first.Parameters[0]; var param = Expression.Parameter(typeof(T), "w");//指定引數和引數名稱 LambdaExpressionParameter lambdaExpression = new LambdaExpressionParameter(param); var left = lambdaExpression.Replace(first.Body); var right = lambdaExpression.Replace(second.Body); var body = Expression.Or(left, right); return Expression.Lambda<Func<T, bool>>(body, param); } /// <summary> /// Expression表示式樹lambda引數拼接--not /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression"></param> /// <returns></returns> public static Expression<Func<T, bool>> Not1<T>(this Expression<Func<T, bool>> expression) { var param = expression.Parameters[0];//指定引數和引數名稱 //var param = Expression.Parameter(typeof(T), "w"); var body = Expression.Not(expression.Body); return Expression.Lambda<Func<T, bool>>(body, param); } } #endregion

測試執行

namespace Test
{
    public class Program
    {

        static void Main(string[] args)
        {
            List<int> grades1 = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            Expression<Func<int, bool>> expression = t => true;
            expression = expression.And1(t => t > 2);
            expression = expression.And1(t => t < 8);
            var ds = grades1.AsQueryable().Where(expression).ToList();
            foreach (var item in ds)
            {
                Console.WriteLine($"IQueryable:{item}");
            }
 
            Console.Read();
        }
     }
}