一、创建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#比较两个对象中的指定字段值是否相等的更多相关文章

  1. mongodb 如何删除 字段值为 json对象中的某个字段值

    例如: { attributes: { birthday:'1988-01-01', name: 'aq' } } birthday是attributes字段的value的一个字段, 我要删除birt ...

  2. SQL查找TCar表中同一辆车前后两条记录的CarId,两条记录中有多个字段值一样

    查询同一个表中某一字段值相同的记录 select * from 表名 where 字段 in(select 字段 from 表名 group by 字段 having count(1)>1) s ...

  3. js对象中动态读取属性值 动态属性值 js正则表达式全局替换

    $(document).ready(function(){ var exceptionMsg = '${exception.message }'; var exceptionstr = ''; //j ...

  4. MySql存储过程批量删除多个数据库中同名表中的指定字段

    1. 创建存储过程batchDeleteField:删除所有名称为"MyDB_"开头的数据库中的指定字段 -- ---------------------------- -- Pr ...

  5. GridView控件RowDataBound事件中获取列字段值的几种途径

    前台: <asp:TemplateField HeaderText="充值总额|账号余额"> <ItemTemplate> <asp:Label ID ...

  6. 使用LINQ获取List列表中的某个字段值

    使用LINQ获取列表中的某个字段值,下面以获取员工列表中的编号字段为例子. 1.使用Select方法 List<Emplayee> emplayeeList = GetEmplayeeLi ...

  7. .NET中利用反射来实现自动映射两个对象中的数据成员

    在以前的项目开发之中,经常会遇到这样一个问题:比如在外面项目的架构设计之中,我们采用MVC和EntityFramework来构建一个Web应用程序.比如我们采用常用的多层架构,例如有Presentat ...

  8. Java中对比两个对象中属性值[反射、注解]

    在Java中通常要比较两个对象在修改前与修改后的值是否相同,一般我们采用的是反射技术获取对象的get方法[或其他的方法]获取值并做比较.如果系统将修改的属性名称也显示出来,这样就能更直观的显示类中的哪 ...

  9. java利用反射交换两个对象中的字段相同的字段值

    有时候我们的两个对象字段都是一样的,只有极少的区别,想要把一个对象字段的值,赋值给另外一个对象值 然后传给另外一个方法使用,但是这个字段太多,一个一个的复制太过繁琐. 这时候利用反射解决这个问题. c ...

随机推荐

  1. C语言程序设计100例之(19):欢乐的跳

    例19   欢乐的跳 题目描述 一个n个元素的整数数组,如果数组两个连续元素之间差的绝对值包括了[1,n-1]之间的所有整数,则称之符合“欢乐的跳”,如数组1 4 2 3符合“欢乐的跳”,因为差的绝对 ...

  2. linux配置LAMP(CentOS7.4 Apache2.4 PHP5.6)

    1.安装Apache 这个就不手动安装了,直接上脚本执行 bash apache.sh 以下为脚本的内容: #!/bin/bashversion=`lsb_release -a|grep Releas ...

  3. javascript截取字符串的最后几个字符

    在JavaScript中截取字符串一般是使用内置的substring()方法和substr()方法,这两个方法功能都很强大,也都能实现截取字符串中的最后几个字符. substring()方法 Java ...

  4. 记一次Ubuntu19无法安装docker源

    按照各大网站以及个人习惯我会使用下面这种方法添加Docker源: root@ubuntu:~# sudo add-apt-repository "deb [arch=amd64] https ...

  5. 一起学SpringMVC之注解

    概述 SpringMVC不仅提供了Xml的配置方式,还提供了注解的方式来声明一个Controller,本文属于SpringMVC的入门级内容,仅供学习分享使用,如有不足之处,还请指正. SpringM ...

  6. python跳出多重循环的方法

    方法1:自定义异常 # -*- coding:utf-8 -*- """ 功能:python跳出循环 """ # 方法1:自定义异常 cla ...

  7. js获取时间,循环执行任务,延迟执行任务

    一.获取时间 核心方法创建一个时间对象:new Date() 时间对象相关操作 时间对象.函数名 函数名 功能 getYear() 获取四位数的年份 getMonth() 获取2位数的月数, 这个是从 ...

  8. .Net Core MVC理解新管道处理模型、中间件

    .Net Core中间件官网:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore ...

  9. linux学习(十)Shell中的控制语句

    目录 1. 条件测试语句 1.1 test语句 1.2[]语句 1.3文件测试 1.4字符串测试 1.5数值测试 1.5逻辑操作符 @(Shell中的控制语句) 1. 条件测试语句 测试语句十Shel ...

  10. 安装HomeBrew 失败的解决方案(Error: Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core failed!)

    在安装HomeBrew(或者安装成功 执行相关指令)时遇到错误提示: Error: Failure while executing: git clone https://github.com/Home ...