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 ...
随机推荐
- 推荐几本高质量的Python书籍--附github下载路径
一 为什么要分享? 最近碰到了一些人和事,感触挺大的.就是发现很多类似自己的软件工程师,一旦工作三五年之后,工作中算是一个熟练工,但是进步的脚步突然慢了下来,虽然你在工作中仍旧很努力.到底是什么原因呢 ...
- App 自动化框架设计思路
最近在整理和学习Appium+Java 自动化框架,对APP自动化框架的部分设想参考了一些文章,先进行整理下: 框架的思路一: 思考引入:https://www.cnblogs.com/yunfeio ...
- 使用IntelliJ IDEA创建第一个Mawen项目
咳咳...首先各位在学习SSM框架的时候,单个单个学完之后,老夫掐指一算(其实,我是个小鲜肉),各位必定会去整合SSM,这个时候,老夫又掐指一算,各位必定会碰到个mawen的东西,在这里,我可以告诉各 ...
- Linux系统彻底卸载MySQL数据库
一.首先查询系统是否安装了MySQL rpm -qa | grep -i mysql 输出结果表示,我安装的MySQL Server,Client都是5.6.44的,因为我系统支持的版本是要5.7+的 ...
- 基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目
一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...
- C#二位数组 数组矩阵对角线之和
二维数组: public static void Main(string[] args) { int[,] a = new int[3, 3]; Random rom = new Random(); ...
- Python中Collections模块的Counter容器类使用教程
1.collections模块 collections模块自Python 2.4版本开始被引入,包含了dict.set.list.tuple以外的一些特殊的容器类型,分别是: OrderedDict类 ...
- Java学习 1.4——第一个Java程序:Hello World!
这一篇一起来写第一个Java程序,同时也了解一下IDEA的使用: 打开IDEA,新建项目: 选择Java,右边project SDK是选择Java版本,上一篇我们自己安装了JDK1.8,IDEA自带一 ...
- javaWeb核心技术第六篇之BootStrap
概述: Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目. 作用: 开发响应式的页面 响应式:就是一个网站能够兼容多个终端 节约开发 ...
- [转]Sumifs函数多条件求和的9个实例
本文转自:http://m.officezhushou.com/sumif/5187.html 第一部分:sumifs函数用法介绍 excel中sumifs函数是Excel2007以后版本新增的多条件 ...