zoukankan      html  css  js  c++  java
  • 比较两个相同类型的实例是否相同, 支持忽略指定字段.

    //翠花, 上代码
    
    var user1 = new User();
    user1.Id = 1;
    user1.Name = "翠花";
    user1.Age = 18;
    
    var user2 = new User();
    user2.Id = 2;
    user2.Name = "二狗";
    user2.Age = 19;
    
    //用法1
    var isEq1 = ObjectUtil.Compare(user1, user2, x=> x.Id);
    
    //用法2
    var isEq2 = ObjectUtil.Compare(user1, user2, x=> new{ x.Id, x.Age });
    public static class ObjectUtil
    {
        /// <summary>
        /// 比较两个同类型的实例是否相同,
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="t1"></param>
        /// <param name="t2"></param>
        /// <param name="ignore">忽略不比较的字段, 可以传入单个字段, 也可以传入匿名类 x=>{ x.Id } </param>
        /// <returns></returns>
        public static bool Compare<TEntity>(TEntity t1, TEntity t2, Expression<Func<TEntity, object>> ignore)
        {
            /*
             * 优化方向: 缓存通过反射取得的属性.
             */
    
            //取所有属性, 只取有{get;set;}的属性哦.
            var properties = (typeof(TEntity)).GetProperties();
    
            //拆解传入的表达式
            var ignoreProperty = Extract(ignore);
    
            //判断忽略模式, 是单字段还是多字段. 下面判断会不一样
            var isManyIgnore = ignoreProperty.Contains(",");
            if (isManyIgnore)
            {
                //加个逗号做边界,增加比较精准度.
                ignoreProperty = $",{ignoreProperty},";
            }
    
            foreach (var property in properties)
            {
                var pName = property.Name;
                if (isManyIgnore && ignoreProperty.Contains($",{pName},"))
                {
                    continue;
                }
                else
                {
                    if (ignoreProperty == pName)
                    {
                        continue;
                    }
                }
    
                var v1 = GetPropertyValue(t1, property);
                var v2 = GetPropertyValue(t2, property);
    
                //只要有一对字段不相等. 就结束循环. 后面的不用比了.
                if (!v1.Equals(v2))
                {
                    return false;
                }
            }
    
            return true;
        }
    
        #region 私有方法
        /*
         * 拆解表达式代码来自github项目52Chloe
         * 改造增加拆解匿名类表达式功能.
         * https://github.com/shuxinqin/Chloe/blob/481fcfd7ce260f7a31b0adde07311c5b25219829/src/Chloe/Entity/PropertyNameExtractor.cs
         */
        private static string Extract(Expression exp)
        {
            return Visit(exp);
        }
        private static string Visit(Expression exp)
        {
            switch (exp.NodeType)
            {
                case ExpressionType.Lambda:
                    return VisitLambda((LambdaExpression)exp);
                case ExpressionType.MemberAccess:
                    return VisitMemberAccess((MemberExpression)exp);
                case ExpressionType.Convert:
                    return VisitUnary_Convert((UnaryExpression)exp);
                case ExpressionType.New:
                    return VisitProperties(exp);
                default:
                    throw new Exception(string.Format("Unhandled expression type: '{0}'", exp.NodeType));
            }
        }
        private static string VisitLambda(LambdaExpression exp)
        {
            return Visit(exp.Body);
        }
        private static string VisitMemberAccess(MemberExpression exp)
        {
            return exp.Member.Name;
        }
        private static string VisitUnary_Convert(UnaryExpression exp)
        {
            return Visit(exp.Operand);
        }
        private static string VisitProperties(object exp)
        {
            var members = ((NewExpression)exp).Members;
    
            if (members == null || members.Count == 0)
            {
                return string.Empty;
            }
    
            return string.Join(",", members.Select(p => p.Name).ToArray());
        }
        private static object GetPropertyValue<T>(T t, PropertyInfo property)
        {
            return property.GetValue(t);
        }
    
        #endregion
    }

    来都来了, 点个赞再走呗.↓

  • 相关阅读:
    Luogu P1273 有限电视网【树形Dp/树形背包】
    Luogu P1160队列安排【链表/老文搬家】By cellur925
    Luogu P1970 花匠 【线性Dp】 By cellur925
    Luogu P1541 乌龟棋 【线性dp】
    P2885 [USACO07NOV]电话线Telephone Wire——Chemist
    Luogu P3916 图的遍历 【优雅的dfs】【内有待填坑】By cellur925
    状压dp之二之三 炮兵阵地/玉米田 By cellur925
    Luogu P1991 无线通讯网 【最小生成树】
    浅谈并查集 By cellur925【内含题目食物链、银河英雄传说等】
    Luogu P1134 阶乘问题 【数学/乱搞】 By cellur925
  • 原文地址:https://www.cnblogs.com/adinet/p/12442632.html
Copyright © 2011-2022 走看看