• C#比较两个对象中的指定字段值是否相等


    一、创建CompareFieldAttribute标识要比较的字段

    using System;
    
    namespace CompareObjField
    {
        /// <summary>
        /// 标识对象中要比较的属性
        /// </summary>
        [AttributeUsage(AttributeTargets.Property)]
        public class CompareFieldAttribute : Attribute
        {
            /// <summary>
            /// 指定比较目标字段名称
            /// </summary>
            public string TargetFieldName { get; set; }
    
            /// <summary>
            /// 所属数据库表名
            /// </summary>
            public string TableName { get; set; }
    
            /// <summary>
            /// 如果目标对象不存在是否跳过
            /// </summary>
            public bool TargetNotExistsSkip { get; set; }
    
            /// <summary>
            /// 在比较过程中0等于null或""
            /// </summary>
            public bool ZeroEqualNullOrEmpt { get; set; }
    
            /// <summary>
            /// 初始化
            /// </summary>
            public CompareFieldAttribute()
            {
                TargetFieldName = "";
                TableName = "";
                TargetNotExistsSkip = false;
                ZeroEqualNullOrEmpt = true;
            }
            /// <summary>
            /// 初始化
            /// </summary>
            /// <param name="targetFieldName">指定比较目标字段名称</param>
            public CompareFieldAttribute(string targetFieldName)
            {
                TargetFieldName = targetFieldName;
            }
    
            /// <summary>
            /// 初始化
            /// </summary>
            /// <param name="targetFieldName">指定比较目标字段名称</param>
            /// <param name="tableName">所属数据库表名</param>
            /// <param name="targetNotExistsSkip"></param>
            public CompareFieldAttribute(string targetFieldName="", string tableName="", bool targetNotExistsSkip=false)
            {
                TargetFieldName = targetFieldName;
                TableName = tableName;
                TargetNotExistsSkip = targetNotExistsSkip;
            }
    
        }
    }

    二、比较操作类

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;
    
    namespace CompareObjField
    {
        /// <summary>
        /// 比较对象字段值公共类
        /// </summary>
        public static class CompareObj
        {
            /// <summary>
            /// 比较两个对象中的指定字段值是否相等
            /// </summary>
            /// <typeparam name="TSource">要比较的类</typeparam>
            /// <typeparam name="TTarget">原始数据类</typeparam>
            /// <param name="source"></param>
            /// <param name="target"></param>
            /// <returns></returns>
            public static List<DifferenceField> CompareObjFieldValue<TSource, TTarget>(TSource source, TTarget target)
                where TSource : class
                where TTarget : class
            {
                List<DifferenceField> list = new List<DifferenceField>();
                if (source == default(TSource))
                {
                    throw new Exception("比较对象不能为空");
                }
                if (target == default(TTarget))
                {
                    throw new Exception("被比较对象不能为空");
                }
                var sourceType = source.GetType();
                var sourceCompareFields = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(t => t.GetCustomAttributes(typeof(CompareFieldAttribute), false).FirstOrDefault() != null).ToList();
                var targetType = target.GetType();
                var targetFields = targetType.GetProperties().ToList();
                foreach (PropertyInfo property in sourceCompareFields)
                {
                    var compareFieldAttribute = property.GetCustomAttributes(typeof(CompareFieldAttribute), false).FirstOrDefault();
    
                    if (compareFieldAttribute == null) continue;
                    var attributeFieldName = ((CompareFieldAttribute)compareFieldAttribute).TargetFieldName;
                    var attributeTableName = ((CompareFieldAttribute)compareFieldAttribute).TableName;
                    var targetFieldName = attributeFieldName != "" ? attributeFieldName : property.Name;
                    var sourceFielValue = property.GetValue(source) != null ? property.GetValue(source) : "";
    
                    var targetField = targetFields.FirstOrDefault(t => t.Name == targetFieldName);
    
                    if (targetField == default(PropertyInfo))
                    {
                        if (((CompareFieldAttribute)compareFieldAttribute).TargetNotExistsSkip) continue;
                        throw new Exception(string.Format("比较出现异常,目标对象[{0}]不存在[{1}]字段", targetType.Name, targetFieldName));
                    }
                    var targetFieldValue = targetField.GetValue(target) != null ? targetField.GetValue(target).ToString() : "";
                    var describeAttr = property.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault();
                    var describeName = "";
                    if (describeAttr != null)
                    {
                        describeName = ((DisplayAttribute)describeAttr).Name;
                    }
                    try
                    {
                        if (sourceFielValue.ToString().Trim() == targetFieldValue.Trim()) continue;
    
                        if (((CompareFieldAttribute)compareFieldAttribute).ZeroEqualNullOrEmpt)
                        {
                            if ((sourceFielValue.ToString() == "" || sourceFielValue.ToString() == "0") && (targetFieldValue == "" || targetFieldValue == "0")) continue;
                        }
    
                        var isNullable = property.PropertyType.ToString().Contains("System.Nullable");
                        object sourceTypeValue = null;
    
                        if (string.IsNullOrEmpty(sourceFielValue.ToString()))
                        {
                            sourceTypeValue = "";
                        }
                        else
                        {
                            if (isNullable)
                            {
                                sourceTypeValue = Convert.ChangeType(sourceFielValue, Nullable.GetUnderlyingType(property.PropertyType));
                            }
                            else
                            {
                                sourceTypeValue = Convert.ChangeType(sourceFielValue, property.PropertyType);
                            }
                        }
    
    
                        object targetTypeValue = null;
                        if (string.IsNullOrEmpty(targetFieldValue))
                        {
                            if (sourceTypeValue.ToString().IsNumber())
                            {
                                targetFieldValue = "0";
                            }
                        }
                        else
                        {
                            if (isNullable)
                            {
                                targetTypeValue = Convert.ChangeType(targetFieldValue, Nullable.GetUnderlyingType(property.PropertyType));
                            }
                            else
                            {
                                targetTypeValue = Convert.ChangeType(targetFieldValue, property.PropertyType);
                            }
                        }
                        if (targetTypeValue == null) targetTypeValue = "";
                     
                        if (property.PropertyType != typeof(string) && sourceTypeValue.ToString().IsNumber() && targetTypeValue.IsNumber())
                        {
                            if (Math.Abs(Convert.ToDouble(sourceTypeValue) - Convert.ToDouble(targetTypeValue)) > 0)
                            {
                                list.Add(new DifferenceField() { SourceDescribe = describeName, SourceFiledName = property.Name, SourceValue = sourceFielValue, TargetValue = targetFieldValue, TableName = attributeTableName });
                            }
                        }
                        else if (sourceTypeValue.ToString().Trim() != targetTypeValue.ToString().Trim())
                        {
                            list.Add(new DifferenceField() { SourceDescribe = describeName, SourceFiledName = property.Name, SourceValue = sourceFielValue, TargetValue = targetFieldValue, TableName = attributeTableName });
                        }
                    }
                    catch (Exception)
                    {
                        list.Add(new DifferenceField() { SourceDescribe = describeName, SourceFiledName = property.Name, SourceValue = sourceFielValue, TargetValue = targetFieldValue, TableName = attributeTableName });
                    }
                }
                return list;
            }
    
            /// <summary>
            /// 判断字符串是否是数字
            /// </summary>
            /// <param name="num">数字字符串</param>
            /// <returns></returns>
            public static bool IsNumber(this object num)
            {
                try
                {
                    Convert.ToDouble(num);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
    
    
        }
    
        /// <summary>
        /// 比较结果差异对象
        /// </summary>
        public class DifferenceField
        {
            /// <summary>
            /// 比较字段名称
            /// </summary>
            public string SourceDescribe { get; set; }
    
            /// <summary>
            /// 比较字段
            /// </summary>
            public string SourceFiledName { get; set; }
    
            /// <summary>
            /// 字段值
            /// </summary>
            public object SourceValue { get; set; }
    
            /// <summary>
            /// 目标字段值
            /// </summary>
            public object TargetValue { get; set; }
    
            /// <summary>
            /// 所属数据库表名
            /// </summary>
            public string TableName { get; set; }
        }
    
    }

    三、单元测试

    1、定义测试类

    using System;
    using System.ComponentModel.DataAnnotations;
    using CompareObjField;
    
    namespace UnitTestProject1
    {
        public class CompareClass
        {
            [Display(Name = "年龄")]
            [CompareField(ZeroEqualNullOrEmpt = true)]
            public int? Age { get; set; }
    
    
            [Display(Name = "数量")]
            [CompareField(ZeroEqualNullOrEmpt = true)]
            public decimal? Amount { get; set; }
    
    
            [Display(Name = "日期")]
            [CompareField(ZeroEqualNullOrEmpt = true)]
            public DateTime? DateTime { get; set; }
    
    
            [Display(Name = "名称")]
            [CompareField]
            public string FName { get; set; }
    
    
            [Display(Name = "身份证")]
            [CompareField]
            public string IDCard { get; set; }
        }
    
        public class Class2
        {
            public int? Age { get; set; }
    
            public decimal? Amount { get; set; }
    
            public DateTime? DateTime { get; set; }
    
            public string FName { get; set; }
    
            public string IDCard { get; set; }
        }
    
    }

    2、单元测试

    using System;
    using CompareObjField;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Newtonsoft.Json;
    
    namespace UnitTestProject1
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
                CompareClass c1 = new CompareClass() { Age = 1,Amount = 19, FName = "19.00", IDCard = "513709199310151835" };
                Class2 c2 = new Class2() { Age = 3, DateTime = DateTime.Now, Amount = 18, FName = "19", IDCard = "513709199310151836" };
                var res = CompareObj.CompareObjFieldValue(c1, c2);
                Console.Write(JsonConvert.SerializeObject(res));
            }
        }
    }

    3、测试结果


    测试结果中输出了所有差异字段的相关信息

    四、附件下载地址

    下载地址

  • 相关阅读:
    Java 泛型的使用
    IDEA 2017.2.2 环境下使用JUnit
    Tomcat的下载安装及使用
    JavaScript基础知识(二)
    JavaScript基础知识(一)
    CSS3基础(4)——CSS3 渲染属性
    CSS3基础(3)——CSS3 布局属性全接触
    CSS3基础(2)—— 文字与字体相关样式、盒子类型、背景与边框相关样式、变形处理、动画功能
    CSS3 基础(1)——选择器详解
    CSS基础学习笔记
  • 原文地址:https://www.cnblogs.com/zjbky/p/9242401.html
Copyright © 2020-2023  润新知