• 动态LINQ(Lambda表达式)


    1.准备数据实体

            public class Data
            {
                public string AccountNO { get; set; }
    
                public int Count { get; set; }
            }

    创建测试数据

     public static List<Data> GetTestData()
                {
                    Data account = new Data
                    {
                        AccountNO = "01",
                        Count = 1
                    };
    
                    Data account1 = new Data
                    {
                        AccountNO = "02",
                        Count = 2
                    };
    
                    Data account2 = new Data
                    {
                        AccountNO = "03",
                        Count = 3
                    };
    
                    Data account3 = new Data
                    {
                        AccountNO = "04",
                        Count = 4
                    };
    
                    Data account4 = new Data
                    {
                        AccountNO = "05",
                        Count = 5
                    };
                    var rel = new List<Data>
                    {
                        account,
                        account1,
                        account2,
                        account3,
                        account4
                    };
                    return rel;
                }

    2.准备查询条件实体

            public class Condition
            {
                [DynamicExpression(Name = "AccountNO", Operator = "Contains")]
                public string Name { get; set; }
    
                [DynamicExpression(Name = "Count", Operator = ">")]
                public int? Age { get; set; }
            }

    数据实体2个字段一个帐号一个年龄大小

    查询条件2个字段一个姓名(Name帐号)一个年龄(Age)

    为了确保查询字段和数据字段名字保持一直 引用一个自定义特性 在查询条件的每个字段上面标记 

    自定义特性包含2个字段一个Name 需要跟数据实体保持一致的名称(注:必须和数据实体的字段对应) Operator 表示运算逻辑符

    附自定义实体代码

     [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = true)]
        public class DynamicExpressionAttribute : Attribute
        {
            /// <summary>
            /// 名称
            /// </summary>
            public string Name { get; set; }
    
            /// <summary>
            /// 运行符号
            /// </summary>
            public string Operator { get; set; }
        }

    从查询条件中提取特效值的扩展类

        public static class CustomAttributeExtension<TAttribute>
            where TAttribute : Attribute
        {
            /// <summary>
            /// Cache Data
            /// </summary>
            private static readonly Dictionary<string, TAttribute> Cache = new Dictionary<string, TAttribute>();
    
            /// <summary>
            /// 获取CustomAttribute Value
            /// </summary>
            /// <param name="type">实体对象类型</param>
            /// <param name="propertyInfo">实体对象属性信息</param>
            /// <returns>返回Attribute的值,没有则返回null</returns>
            public static TAttribute GetCustomAttributeValue(Type type, PropertyInfo propertyInfo)
            {
                var key = BuildKey(type, propertyInfo);
                if (!Cache.ContainsKey(key))
                {
                    CacheAttributeValue(type, propertyInfo);
                }
                return Cache[key];
            }
    
            /// <summary>
            /// 获取CustomAttribute Value
            /// </summary>
            /// <param name="sourceType">实体对象数据类型</param>
            /// <returns>返回Attribute的值,没有则返回null</returns>
            public static TAttribute GetCustomAttributeValue(Type sourceType)
            {
                var key = BuildKey(sourceType, null);
                if (!Cache.ContainsKey(key))
                {
                    CacheAttributeValue(sourceType, null);
                }
                return Cache[key];
            }
    
            /// <summary>
            /// 获取实体类上的特性
            /// </summary>
            /// <param name="type">实体对象类型</param>
            /// <returns>返回Attribute的值,没有则返回null</returns>
            private static TAttribute GetClassAttributes(Type type)
            {
                var attribute = type.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault();
                return (TAttribute)attribute;
            }
    
            /// <summary>
            /// 获取实体属性上的特性
            /// </summary>
            /// <param name="propertyInfo">属性信息</param>
            /// <returns>返回Attribute的值,没有则返回null</returns>
            private static TAttribute GetPropertyAttributes(PropertyInfo propertyInfo)
            {
                var attribute = propertyInfo?.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault();
                return (TAttribute)attribute;
            }
    
            /// <summary>
            /// 缓存Attribute Value
            /// <param name="type">实体对象类型</param>
            /// <param name="propertyInfo">实体对象属性信息</param>
            /// </summary>
            private static void CacheAttributeValue(Type type, PropertyInfo propertyInfo)
            {
                var key = BuildKey(type, propertyInfo);
                TAttribute value;
                if (propertyInfo == null)
                {
                    value = GetClassAttributes(type);
                }
                else
                {
                    value = GetPropertyAttributes(propertyInfo);
                }
    
                lock (key + "_attributeValueLockKey")
                {
                    if (!Cache.ContainsKey(key))
                    {
                        Cache[key] = value;
                    }
                }
            }
    
            /// <summary>
            /// 缓存Collection Name Key
            /// <param name="type">type</param>
            /// <param name="propertyInfo">propertyInfo</param>
            /// </summary>
            private static string BuildKey(Type type, PropertyInfo propertyInfo)
            {
                if (string.IsNullOrEmpty(propertyInfo?.Name))
                {
                    return type.FullName;
                }
                return type.FullName + "." + propertyInfo.Name;
            }
        }

    根据数据和查询条件生成表达式

     public static Func<TResult, bool> GetDynamicExpression<TResult, TCondition>(this IEnumerable<TResult> data, TCondition condtion)
                where TResult : class
                where TCondition : class
            {
                Type tConditionType = typeof(TCondition);
                Type tResultType = typeof(TResult);
    
                Expression totalExpr = Expression.Constant(true);
                ParameterExpression param = Expression.Parameter(typeof(TResult), "n");
                foreach (PropertyInfo property in tConditionType.GetProperties())
                {
                    string key = property.Name;
                    object value = property.GetValue(condtion);
                    if (value != null && value.ToString() != string.Empty)
                    {
                        DynamicExpressionAttribute dynamicExpressionAttribute = CustomAttributeExtension<DynamicExpressionAttribute>.GetCustomAttributeValue(tConditionType, property);
    
                        //等式左边的值
                        string name = dynamicExpressionAttribute.Name ?? key;
                        Expression left = Expression.Property(param, tResultType.GetProperty(name));
                        //等式右边的值
                        Expression right = Expression.Constant(value);
    
                        Expression filter;
                        switch (dynamicExpressionAttribute.Operator)
                        {
                            case "!=":
                                filter = Expression.NotEqual(left, right);
                                break;
                            case ">":
                                filter = Expression.GreaterThan(left, right);
                                break;
                            case ">=":
                                filter = Expression.GreaterThanOrEqual(left, right);
                                break;
                            case "<":
                                filter = Expression.LessThan(left, right);
                                break;
                            case "<=":
                                filter = Expression.LessThanOrEqual(left, right);
                                break;
                            case "Contains":
                                filter = Expression.Call(Expression.Property(param, tResultType.GetProperty(name)), typeof(string).GetMethod("Contains", new [] { typeof(string) }), Expression.Constant(value)); ;
                                break;
                            default:
                                filter = Expression.Equal(left, right);
                                break;
                        }
                        totalExpr = Expression.And(filter, totalExpr);
                    }
                }
                var predicate = Expression.Lambda(totalExpr, param);
                var dynamic = (Func<TResult, bool>)predicate.Compile();
                return dynamic;
            }

    测试 : (查询帐号包含1的数据)

     public static void Test()
                {
                    var data = GetTestData();
                    var codition = new Condition { Name = "1"};
                    var dynamicExpression = GetDynamicExpression(data, codition);
                    var query1 = data.Where(dynamicExpression);
                }
  • 相关阅读:
    使用mybatis插入自增主键ID的数据后返回自增的ID
    CentOS 配置阿里云 yum 源
    Zabbix监控ActiveMQ
    wget下载阿里云oss的文件报错403
    Zabbix-proxy和Zabbix-agent源码安装
    Zabbix 设置自动添加主机两种方法(自动注册、自动发现)
    Zabbix邮件预警-这个坑我跳了不止一次
    AWS云创建EC2与使用注意事项-踩坑记录
    Zabbix图表中文乱码(包含Docker安装乱码)
    Zabbix server 更改数据库密码
  • 原文地址:https://www.cnblogs.com/liuxiaoji/p/6370721.html
Copyright © 2020-2023  润新知