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() == "") && (targetFieldValue == "" || targetFieldValue == "")) 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 = "";
}
}
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)) > )
{
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 = ,Amount = , FName = "19.00", IDCard = "" };
Class2 c2 = new Class2() { Age = , DateTime = DateTime.Now, Amount = , FName = "", IDCard = "" };
var res = CompareObj.CompareObjFieldValue(c1, c2);
Console.Write(JsonConvert.SerializeObject(res));
}
}
}
3、测试结果
测试结果中输出了所有差异字段的相关信息

四、附件下载地址
C#比较两个对象中的指定字段值是否相等的更多相关文章
- mongodb 如何删除 字段值为 json对象中的某个字段值
例如: { attributes: { birthday:'1988-01-01', name: 'aq' } } birthday是attributes字段的value的一个字段, 我要删除birt ...
- SQL查找TCar表中同一辆车前后两条记录的CarId,两条记录中有多个字段值一样
查询同一个表中某一字段值相同的记录 select * from 表名 where 字段 in(select 字段 from 表名 group by 字段 having count(1)>1) s ...
- js对象中动态读取属性值 动态属性值 js正则表达式全局替换
$(document).ready(function(){ var exceptionMsg = '${exception.message }'; var exceptionstr = ''; //j ...
- MySql存储过程批量删除多个数据库中同名表中的指定字段
1. 创建存储过程batchDeleteField:删除所有名称为"MyDB_"开头的数据库中的指定字段 -- ---------------------------- -- Pr ...
- GridView控件RowDataBound事件中获取列字段值的几种途径
前台: <asp:TemplateField HeaderText="充值总额|账号余额"> <ItemTemplate> <asp:Label ID ...
- 使用LINQ获取List列表中的某个字段值
使用LINQ获取列表中的某个字段值,下面以获取员工列表中的编号字段为例子. 1.使用Select方法 List<Emplayee> emplayeeList = GetEmplayeeLi ...
- .NET中利用反射来实现自动映射两个对象中的数据成员
在以前的项目开发之中,经常会遇到这样一个问题:比如在外面项目的架构设计之中,我们采用MVC和EntityFramework来构建一个Web应用程序.比如我们采用常用的多层架构,例如有Presentat ...
- Java中对比两个对象中属性值[反射、注解]
在Java中通常要比较两个对象在修改前与修改后的值是否相同,一般我们采用的是反射技术获取对象的get方法[或其他的方法]获取值并做比较.如果系统将修改的属性名称也显示出来,这样就能更直观的显示类中的哪 ...
- java利用反射交换两个对象中的字段相同的字段值
有时候我们的两个对象字段都是一样的,只有极少的区别,想要把一个对象字段的值,赋值给另外一个对象值 然后传给另外一个方法使用,但是这个字段太多,一个一个的复制太过繁琐. 这时候利用反射解决这个问题. c ...
随机推荐
- json解决ajax跨域的原理
jsonp只能解决GET类型的ajax请求跨域问题 jsonp请求不是ajax请求,而是一般的get请求 基本原理 浏览器端: 动态生成<script>来请求后台接口(src就是接口的ur ...
- ReactNative: 使用标签栏组件TabBarIOS组件
一.简介 标签栏Tab的作用对于应用程序那是不言而喻的,它是应用程序中除了导航栏组件外的又一个核心组件,使用它可以实现页面的切换.RN提供了一个TabBarIOS组件来完成页面的切换(视图或者路由), ...
- laravel实现多模块
一.这里使用Caffienate Modules 网址:modules maintained by caffeinated 二.根据自己的版本选择包的版本 三.在项目composer.json文件中加 ...
- php获取本机ip
最近在写个东西时,需要获取本机的IP,但是由于php本身不带这样的功能,在网上找了好久也没有一个好办法,突然想到一个好办法,如下代码 <?=gethostbyname($_ENV['COMPUT ...
- boostrap 学习笔记
bootstrap : 是全球最受欢迎的前端组件库,用于开发响应式布局.移动设备优先的 WEB 项目. 用于项目样式的快速搭建,真的是..特别快.. 随便找两个cdn引用就能使用了. https:// ...
- Good start is a half success(2019-04-07)
一. 回顾你过去将近3年的学习经历. (1)当初你报考的时候,是真正喜欢计算机这个专业吗?. (2)你现在后悔选择了这个专业吗?. (3)你认为你现在最喜欢的领域是什么(可以是计算机的也可以是其它领域 ...
- RAC ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance
重启RAC时发现32004,后来才发现DG已经不存在了standby_archive_dest还在生效中,而background_dump_dest和user_dump_dest并没在pfile中出现 ...
- ramdisk配置、解压、创建rootfs、启动简单分析
关键词:ramdisk.rdint..init.ramfs.__initramfs_start.__initramfs_size.rootfs.ramfs.populate_rootfs().gzip ...
- go设计模式--单例singleton
创建型第一个,使用TDD作的. singleton.go package singleton type Singleton interface { AddOne() int } type single ...
- new String(request.getParameter("userID").trim().getBytes("8859_1"))的含义是什么?
new String(request.getParameter("userID").trim().getBytes("8859_1")) request.get ...