在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、创建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、测试结果
四、附件下载地址 |
请发表评论