Expression之动态比较实体属性

(33) 2023-10-12 14:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说Expression之动态比较实体属性,希望能够帮助你!!!。

在开发开发过程中,有时候我们要根据用户传入的信息或数据库中设定的信息对不同类实体的属性进行比较以便进行下面的逻辑,比如定义一个用户类UserIfno,如下

public class UserInfo
{

    /// <summary>
    /// 用户编号
    /// </summary>
    public string UserNo { get; set; }

    /// <summary>
    /// 用户名称
    /// </summary>
    public string UserName { get; set; }

    /// <summary>
    /// 性别
    /// </summary>
    public string Sex { get; set; }

    /// <summary>
    /// 出生日期
    /// </summary>
    public DateTime BirthDay { get; set; }

    /// <summary>
    /// 班级
    /// </summary>
    public string Class { get; set; }
}

统计如下条件的数量

1、性别为男的数量

2、性别为女的数量

3、班级为A的数量

4、班级为B的数量

5、性别为男、班级为A的数量

一般要是统计以上5种数量,要写5个统计表达式,具体过程如下

新建一个生成数据源的类,命名为 CreateData

public class CreateData
{
    public static List<UserInfo> Create()
    {
        List<UserInfo> uiList = new List<UserInfo>();
        uiList.Add(new UserInfo() { UserNo = "1", UserName = "张1", Sex = "男", Class = "A" });
        uiList.Add(new UserInfo() { UserNo = "2", UserName = "张2", Sex = "男", Class = "B" });
        uiList.Add(new UserInfo() { UserNo = "3", UserName = "张3", Sex = "男", Class = "B" });
        uiList.Add(new UserInfo() { UserNo = "4", UserName = "张4", Sex = "女", Class = "A" });
        uiList.Add(new UserInfo() { UserNo = "5", UserName = "张5", Sex = "男", Class = "A" });
        uiList.Add(new UserInfo() { UserNo = "6", UserName = "张6", Sex = "男", Class = "B" });
        uiList.Add(new UserInfo() { UserNo = "7", UserName = "张7", Sex = "女", Class = "A" });
        uiList.Add(new UserInfo() { UserNo = "8", UserName = "张8", Sex = "男", Class = "A" });
        uiList.Add(new UserInfo() { UserNo = "9", UserName = "张9", Sex = "男", Class = "B" });
        uiList.Add(new UserInfo() { UserNo = "10", UserName = "张10", Sex = "女", Class = "A" });
        uiList.Add(new UserInfo() { UserNo = "11", UserName = "张11", Sex = "男", Class = "B" });
        uiList.Add(new UserInfo() { UserNo = "12", UserName = "张12", Sex = "男", Class = "A" });
        return uiList;
    }
}

开始统计

int Sex1Count = uiList.Count(p => p.Sex == 1);
int Sex0Count = uiList.Count(p => p.Sex == 0);
int ClassACount = uiList.Count(p => p.Class == "A");
int ClassBCount = uiList.Count(p => p.Class == "B");
int Sex1ClassACount = uiList.Count(p => p.Sex == 1 && p.Class == "A");

以上,如果我们要再增加条件,又得写一条统计语句,如果要减少一个条件,又得删除统计语句,并且如果条件是的数据库中动态配置的,上面的写法肯定是不行的,能不能弄一个可配置的统计呢,当然是可以的,定义一个类,命名为:ExpressionCompare,如下

public static class ExpressionCompare
{
    //创建True表达式
    public static Expression<Func<T, bool>> True<T>()
    {
        return p => true;
    }

    /// <summary>
    /// 构造等于表达式
    /// </summary>
    /// <typeparam name="T">泛型类型</typeparam>
    /// <param name="propertyName">属性名称</param>
    /// <param name="value">属性值</param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> BulidEqualPredicate<T>(string propertyName, string value)
    {
        Type tType = typeof(T);
        //创建传入实体的参数表达式
        ParameterExpression leftParaExp = Expression.Parameter(tType, "p");
        //获得传入实体的属性
        PropertyInfo pi = tType.GetProperty(propertyName);
        //创建传入实体的属性表达式
        MemberExpression leftExp = Expression.Property(leftParaExp, pi);
        //根据value创建学量表达式
        ConstantExpression valueExp = Expression.Constant(value);
        //创建比较表达式
        BinaryExpression equalExp = Expression.Equal(leftExp, valueExp);
        //生成委托
        Expression<Func<T, bool>> lamb = Expression.Lambda<Func<T, bool>>(equalExp, leftParaExp);
        return lamb;
    }

    /// <summary>
    /// 用户且的关系合并两个表达式
    /// </summary>
    /// <typeparam name="T">泛型类型</typeparam>
    /// <param name="left">左边的表达式</param>
    /// <param name="right">右边的表达式</param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
    {
        //用left的参数定义right的参数,要不然left和right的参数不一致
        var invokeExpre = Expression.Invoke(right, left.Parameters.Cast<Expression>());
        //用AND合并两个表达式
        BinaryExpression exp = Expression.And(left.Body, invokeExpre);
        //返回合并后的表达式
        return Expression.Lambda<Func<T, bool>>(exp, left.Parameters);
    }
}

修改 Program.cs 的方法

class Program
{
    static void Main(string[] args)
    {
        //生成数据源
        List<UserInfo> uiList = CreateData.Create();

        //配置统计条件
        List<Conditions> groups = new List<Conditions>()
            {
                new Conditions(){Name="Sex0Count",CompareFields = new List<CompareField>(){
                    new CompareField() { Field = "Sex", Value = "男" }
                } },
                new Conditions(){Name="Sex1Count",CompareFields = new List<CompareField>(){
                    new CompareField() { Field = "Sex", Value = "女" }
                } },
                new Conditions(){Name="ClassACount",CompareFields = new List<CompareField>(){
                    new CompareField() { Field = "Class", Value = "A" }
                } },
                new Conditions(){Name="ClassBCount",CompareFields = new List<CompareField>(){
                    new CompareField() { Field = "Class", Value = "B" }
                } },
                new Conditions(){Name="Sex1ClassA",CompareFields = new List<CompareField>(){
                    new CompareField() { Field = "Sex", Value = "男" } ,
                    new CompareField() { Field = "Class", Value = "A" }
                } }
            };

        //根据条件动态统计
        foreach (var group in groups)
        {
            var predicate = ExpressionCompare.True<UserInfo>();
            var temp = predicate.Compile();
            for (int i = 0; i < group.CompareFields.Count; i++)
            {
                var condition = group.CompareFields[i];
                var newPredicate = ExpressionCompare.BulidEqualPredicate<UserInfo>(condition.Field, condition.Value);
                predicate = predicate.And(newPredicate);
            }
            int iCount = uiList.Count(predicate.Compile());
            Console.WriteLine(#34;{group.Name}: {iCount}");
        }
    }
}

生成的结果 如下:

Expression之动态比较实体属性_https://bianchenghao6.com/blog__第1张

如果要修改统计逻辑,我们只要修改配置条件就可以了,如果配置条件是在数据库中,只要修改数据库里的配置信息后就可以了,统计方法不用修改

List<Conditions> groups = new List<Conditions>()
{
    new Conditions(){Name="ClassACount",CompareFields = new List<CompareField>(){
        new CompareField() { Field = "Class", Value = "A" }
    } },
    new Conditions(){Name="Sex1Count",CompareFields = new List<CompareField>(){
        new CompareField() { Field = "Sex", Value = "女" }
    } },
    new Conditions(){Name="ClassASex0Count",CompareFields = new List<CompareField>(){
        new CompareField() { Field = "Class", Value = "A" },
        new CompareField() { Field = "Sex", Value = "女" }
    } },
    new Conditions(){Name="Sex1ClassA",CompareFields = new List<CompareField>(){
        new CompareField() { Field = "Sex", Value = "男" } ,
        new CompareField() { Field = "Class", Value = "A" }
    } }
};
Expression之动态比较实体属性_https://bianchenghao6.com/blog__第2张

以上就是动态配置统计信息的一种方法

更多的配置,大家可以自定义自己的Expression表大家式构造类

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复