一、创建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. 【STM32-V7】STM32H743XIH6开发板,丰富软件资源,强劲硬件配置,大量软件解决方案持续更新中(2019-12-12)

    说明: 争取做更多的实战性应用,分享更多的嵌入式技术,希望能在实际项目中帮到大家. (1)V7将大力加强对初学者的支持力度,已经更新至63章,下载链接,后37章和一批视频教程将加紧制作. (2)事隔五 ...

  2. github用户注册和仓库创建

    访问github官网:https://github.com/,点击注册进入注册页面 输入用户名,电子邮箱和密码后点击下一步 邮箱验证,收到github的验证邮箱,打开后点击验证 选择个人计划 创建仓库 ...

  3. python的pstuil模块总结

    import psutil print(dir(psutil)) # 查看逻辑cpu的个数 print(psutil.cpu_count()) # 查看物理cpu的个数 print(psutil.cp ...

  4. PHP 核心特性 - 错误处理

    错误与异常 错误,可以理解程序本身的错误,例如语法错误.而异常则更偏向于程序运行不符合预期或者不符合正常流程:对于 PHP 语言而言,处理错误和处理异常使用的机制完全不同,因此很容易让人产生困惑. 例 ...

  5. Python 一键获取百度网盘提取码

    该 GIF 图来自于官网,文末有给出链接. 描述 依托于百度网盘巨大的的云存储空间,绝大数人会习惯性的将一些资料什么的存储到上面,但是有的私密链接需要提取码,但是让每个想下载私密资源的人记住每一个提取 ...

  6. 即将是史上最全的meta大全

    本文的目的是搜集当前主流的meta配置,方便开发者快速开发调试.在这里不会做各种meta的深入分析,只是简单的介绍,让大家知道有这个东西. meta简述 meta用于描述 HTML 文档的元数据.通常 ...

  7. PHP安全之道学习笔记4:系统命令注入

    系统命令注入 我们有时候写代码会用php脚本去调用系统函数完成业务功能,但是一些系统函数属于高危操作,一旦被webshell或者抓住漏洞则后患极大. 下面整理如下风险系统函数. exec() 函数 该 ...

  8. python文件夹遍历,文件操作,获取文件修改创建时间

    在Python中,文件操作主要来自os模块,主要方法如下: os.listdir(dirname):列出dirname下的目录和文件os.getcwd():获得当前工作目录os.curdir:返回当前 ...

  9. Java 网络编程初探

    Java 网络编程 网络编程 网络编程:进行服务器端与客户端编程的开发操作实现. java.net:网络操作包 B/S结构: 浏览器/服务器模式(Browser/Server) 不在开发客户端代码 开 ...

  10. GetPrivateProfileInt 使用方法

    GetPrivateProfileInt =>从ini文件取得数值 <参数> lpApplicationName String,指定在其中查找条目的小节.注意这个字串是不区分大小写的 ...