反射实现Model修改前后的内容对比
在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责。
首先我们要创建一个User类
public class User
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string age;
public string Age
{
get { return age; }
set { age = value; }
}
private string sex;
public string Sex
{
get { return sex; }
set { sex = value; }
}
}
然后在Main函数中声明并初始化一个User对象
User userA = new User()
{
Name = "李四",
Age = "",
Sex = "男",
};
因为要对比对象编辑前后的内容,所以需要备份一下这个UserA,我们来个深拷贝
User userB = DeepCopyByXml<User>(userA);
/// <summary>
/// 深拷贝
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T DeepCopyByXml<T>(T obj) where T : class
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
XmlSerializer xml = new XmlSerializer(typeof(T));
xml.Serialize(ms, obj);
ms.Seek(, SeekOrigin.Begin);
retval = xml.Deserialize(ms);
ms.Close();
}
return (T)retval;
}
接下来的工作是修改UserA的属性,然后和UserB对比,利用反射来实现该功能
/// <summary>
/// Model对比
/// </summary>
/// <typeparam Name="T"></typeparam>
/// <param Name="oldModel"></param>
/// <param Name="newModel"></param>
private static void CompareModel<T>(T oldModel, T newModel) where T : class
{
string changeStr = string.Empty;
PropertyInfo[] properties = oldModel.GetType().GetProperties();
Console.WriteLine("--------用户信息修改汇总--------");
foreach (System.Reflection.PropertyInfo item in properties)
{string name = item.Name;
object oldValue = item.GetValue(oldModel);
object newValue = item.GetValue(newModel);
if (!oldValue.Equals(newValue))
{
Console.WriteLine(name + " :由[" + oldValue + "] 改为 [" + newValue + "]");
}
}
}

从运行结果来看我们已经获取到了修改的内容,美中不足的是“Name”和“Age”,如何以中文显示属性名,接下来将利用C#的特性来实现
新建一个自定义的特性类TableAttribute
/*
参数 validon 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
参数 allowmultiple(可选的)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)。
参数 inherited(可选的)为该特性的 Inherited 属性(property)提供一个布尔值。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)。
*/
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Field |
AttributeTargets.Property,
AllowMultiple = false,
Inherited = false)]
public class TableAttribute : System.Attribute
{
private string fieldName;
private string tableName;
/// <summary>
/// 表名
/// </summary>
public string TableName
{
get { return tableName; }
set { tableName = value; }
}
/// <summary>
/// 字段名
/// </summary>
public string FieldName
{
get { return fieldName; }
set { fieldName = value; }
}
}
接着修改User类,加上自定义的特性TableAttribute
/// <summary>
/// 用户信息实体类
/// </summary>
[TableAttribute(TableName = "用户信息")]
public class User
{
private string name;
[TableAttribute(FieldName = "姓名")]
public string Name
{
get { return name; }
set { name = value; }
}
private string age;
[TableAttribute(FieldName = "年龄")]
public string Age
{
get { return age; }
set { age = value; }
}
private string sex;
[TableAttribute(FieldName = "性别")]
public string Sex
{
get { return sex; }
set { sex = value; }
}
}
最后修改一下CompareModel这个方法
/// <summary>
/// Model对比
/// </summary>
/// <typeparam Name="T"></typeparam>
/// <param Name="oldModel"></param>
/// <param Name="newModel"></param>
private static void CompareModel<T>(T oldModel, T newModel) where T : class
{
string changeStr = string.Empty;
PropertyInfo[] properties = oldModel.GetType().GetProperties();
Console.WriteLine("--------用户信息修改汇总--------");
foreach (System.Reflection.PropertyInfo item in properties)
{
TableAttribute tableAttribute = item.GetCustomAttribute<TableAttribute>();
string name = item.Name;
if (tableAttribute != null)
name = tableAttribute.FieldName;
object oldValue = item.GetValue(oldModel);
object newValue = item.GetValue(newModel);
if (!oldValue.Equals(newValue))
{
Console.WriteLine(name + " :由[" + oldValue + "] 改为 [" + newValue + "]");
}
}
}
我们看一下运行结果

完整demo下载:https://files.cnblogs.com/files/LikeHeart/ExampleReflection.zip
(完)
反射实现Model修改前后的内容对比的更多相关文章
- 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习
反射实现Model修改前后的内容对比 在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...
- Charles系列三:Charles打断点(包含修改请求,修改返回的内容),模拟慢速网络(弱网测试),域名映射,过滤请求,接口调试,打压测试
一:Charles断点的使用(包含修改请求,修改返回的数据) 设置断点来修改请求和返回的数据,在开发过程中可以模拟多种响应.步骤如下: 1.添加断点方法有两种: 方法1:找到Charles中菜单项Pr ...
- 修改placeholder提示内容的颜色以及文本框输入文字内容的颜色
一般表单文本框提示信息:placeholder=" ",默认颜色是灰色的,输入文本信息也是默认为黑色的,如图所示: 修改placeholder提示内容的颜色关键代码及实现: 实现输 ...
- ios UIWebView截获html并修改便签内容(转载)
ios UIWebView截获html并修改便签内容 博客分类: iphone开发iphone开发phoneGap uiwebviewstringByEvaluatingJavaScriptFromS ...
- IOS UIWebView截获html并修改便签内容,宽度自适应
需求:混合应用UIWebView打开html后,UIWebView有左右滚动条,要去掉左右滚动效果: 方法:通过js截获UIWebView中的html,然后修改html标签内容: 实例代码: 服 ...
- ios UIWebView截获html并修改便签内容
需求:混合应用UIWebView打开html后,UIWebView有左右滚动条,要去掉左右滚动效果: 方法:通过js截获UIWebView中的html,然后修改html标签内容: 实例代码: 服务器端 ...
- Mac下显示隐藏文件 以及修改 hosts文件内容
修改hosts 文件内容: 进入etc 文件夹,找到hosts 文件,把该文件复制出来,修改完里面的内容后,先把etc中的hosts 文件删除,然后在把修改后的文件脱机去 可能需要管理员的密码,你输入 ...
- 简单的爬虫爬的完整的<img>标签,修改正则即可修改爬取内容
简单的爬虫爬的完整的<img>标签,生成<img>标签结果文件与爬虫经历的网页. <?php/** 从给定的url获取html内容** */function _getUr ...
- OpenXml修改word特定内容
采用OpenXml来修改word特定内容,如下: word: OpenXml修改word之前: OpenXml修改word之后: 代码: string path = @"C:\Users\A ...
随机推荐
- NLog配置JsonLayout中文输出为unicode问题
日志输出现要改为json格式,网上查询layout配置为JsonLayout就可以了,结果发现输出中文为unicode编码,看很多文章说配置encode="false"就可以了,结 ...
- JQuery Mobile - 自定义图标!
环境 jquery1.9.1.js jquery mobile 1.4.2版 图标制作 18x18px 底透明的png图标 使用图标,这个过程开始怎么弄都不行,只有个灰色的圆出现,不见图标:或者出现图 ...
- 【环境学习】ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞
环境保留:2019.4.4-4.10 环境搭建: 这里我使用的是:vulhub vulhub目录结构:vulhub/thinkphp/5-rcess 测试地址(开放一段时间供大家学习):http:// ...
- 跟着刚哥学习Spring框架--JDBC(六)
Spring的JDBC框架 Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发. Spring主要提供JDBC模板方式.关系数据库对象化方式.SimpleJdbc方式.事务管理来简 ...
- 锐捷客户端下虚拟机VMware无法联网的问题
打开VMware,选择右下角的网络适配器,设置为NAT模式. 如果还不能上网,则打开电脑的任务管理器,保证VMwate的服务保持开启. 但是锐捷客户端,会自动检测并且关闭VMware NAT Serv ...
- 剑指offer五之用两个栈实现队列
一.题目 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 二.思路 1.Push操作:将数据直接压入stack1即可 2.Pop操作:将stack1中的数据全部弹 ...
- MVC3学习:利用mvc3+ajax检测用户是否被注册
假设用户名是保存在表Users中.关系模式为Users(Uid,UserName,PassWord) 可先利用mvc自带的模板生成Create页面. 将填写用户名的地方,由原来的 <div cl ...
- Android通用简洁的下载器
下载逻辑在android开发中可谓很常见,那么封装一个通用简洁的下载器时很有必要的.如果不想给工程引入一个很重的jar包那么可以直接复用下面的代码即可. 主要对外接口 构造函数 : publi ...
- Linux驱动:I2C驱动编写要点
继续上一篇博文没讲完的内容“针对 RepStart 型i2c设备的驱动模型”,其中涉及的内容有:i2c_client 的注册.i2c_driver 的注册.驱动程序的编写. 一.i2c 设备的注册分析 ...
- Zookeeper--0200--安装与集群搭建、常用命令、客户端工具
看这里,http://www.cnblogs.com/lihaoyang/p/8358153.html 1,先使用可视化客户端软件 ZooInspector 连接上集群中的一个节点,看下zk的结构: ...