在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责。

首先我们要创建一个User类

  1. public class User
  2. {
  3. private string name;
  4. public string Name
  5. {
  6. get { return name; }
  7. set { name = value; }
  8. }
  9. private string age;
  10. public string Age
  11. {
  12. get { return age; }
  13. set { age = value; }
  14. }
  15. private string sex;
  16. public string Sex
  17. {
  18. get { return sex; }
  19. set { sex = value; }
  20. }
  21. }

然后在Main函数中声明并初始化一个User对象

  1. User userA = new User()
  2. {
  3. Name = "李四",
  4. Age = "",
  5. Sex = "男",
  6. };

因为要对比对象编辑前后的内容,所以需要备份一下这个UserA,我们来个深拷贝

  1. User userB = DeepCopyByXml<User>(userA);
  1. /// <summary>
  2. /// 深拷贝
  3. /// </summary>
  4. /// <typeparam name="T"></typeparam>
  5. /// <param name="obj"></param>
  6. /// <returns></returns>
  7. public static T DeepCopyByXml<T>(T obj) where T : class
  8. {
  9. object retval;
  10. using (MemoryStream ms = new MemoryStream())
  11. {
  12. XmlSerializer xml = new XmlSerializer(typeof(T));
  13. xml.Serialize(ms, obj);
  14. ms.Seek(, SeekOrigin.Begin);
  15. retval = xml.Deserialize(ms);
  16. ms.Close();
  17. }
  18. return (T)retval;
  19. }

接下来的工作是修改UserA的属性,然后和UserB对比,利用反射来实现该功能

  1. /// <summary>
  2. /// Model对比
  3. /// </summary>
  4. /// <typeparam Name="T"></typeparam>
  5. /// <param Name="oldModel"></param>
  6. /// <param Name="newModel"></param>
  7. private static void CompareModel<T>(T oldModel, T newModel) where T : class
  8. {
  9. string changeStr = string.Empty;
  10. PropertyInfo[] properties = oldModel.GetType().GetProperties();
  11. Console.WriteLine("--------用户信息修改汇总--------");
  12. foreach (System.Reflection.PropertyInfo item in properties)
  13. {string name = item.Name;
  14. object oldValue = item.GetValue(oldModel);
  15. object newValue = item.GetValue(newModel);
  16. if (!oldValue.Equals(newValue))
  17. {
  18. Console.WriteLine(name + " :由[" + oldValue + "] 改为 [" + newValue + "]");
  19. }
  20. }
  21. }

从运行结果来看我们已经获取到了修改的内容,美中不足的是“Name”和“Age”,如何以中文显示属性名,接下来将利用C#的特性来实现

新建一个自定义的特性类TableAttribute

  1. /*
  2. 参数 validon 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
  3. 参数 allowmultiple(可选的)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)。
  4. 参数 inherited(可选的)为该特性的 Inherited 属性(property)提供一个布尔值。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)。
  5. */
  6. [AttributeUsage(AttributeTargets.Class |
  7. AttributeTargets.Field |
  8. AttributeTargets.Property,
  9. AllowMultiple = false,
  10. Inherited = false)]
  11. public class TableAttribute : System.Attribute
  12. {
  13. private string fieldName;
  14. private string tableName;
  15. /// <summary>
  16. /// 表名
  17. /// </summary>
  18. public string TableName
  19. {
  20. get { return tableName; }
  21. set { tableName = value; }
  22. }
  23. /// <summary>
  24. /// 字段名
  25. /// </summary>
  26. public string FieldName
  27. {
  28. get { return fieldName; }
  29. set { fieldName = value; }
  30. }
  31. }

接着修改User类,加上自定义的特性TableAttribute

  1. /// <summary>
  2. /// 用户信息实体类
  3. /// </summary>
  4. [TableAttribute(TableName = "用户信息")]
  5. public class User
  6. {
  7. private string name;
  8. [TableAttribute(FieldName = "姓名")]
  9. public string Name
  10. {
  11. get { return name; }
  12. set { name = value; }
  13. }
  14. private string age;
  15. [TableAttribute(FieldName = "年龄")]
  16. public string Age
  17. {
  18. get { return age; }
  19. set { age = value; }
  20. }
  21. private string sex;
  22. [TableAttribute(FieldName = "性别")]
  23. public string Sex
  24. {
  25. get { return sex; }
  26. set { sex = value; }
  27. }
  28. }

最后修改一下CompareModel这个方法

  1. /// <summary>
  2. /// Model对比
  3. /// </summary>
  4. /// <typeparam Name="T"></typeparam>
  5. /// <param Name="oldModel"></param>
  6. /// <param Name="newModel"></param>
  7. private static void CompareModel<T>(T oldModel, T newModel) where T : class
  8. {
  9. string changeStr = string.Empty;
  10. PropertyInfo[] properties = oldModel.GetType().GetProperties();
  11. Console.WriteLine("--------用户信息修改汇总--------");
  12. foreach (System.Reflection.PropertyInfo item in properties)
  13. {
  14. TableAttribute tableAttribute = item.GetCustomAttribute<TableAttribute>();
  15. string name = item.Name;
  16. if (tableAttribute != null)
  17. name = tableAttribute.FieldName;
  18. object oldValue = item.GetValue(oldModel);
  19. object newValue = item.GetValue(newModel);
  20. if (!oldValue.Equals(newValue))
  21. {
  22. Console.WriteLine(name + " :由[" + oldValue + "] 改为 [" + newValue + "]");
  23. }
  24. }
  25. }

我们看一下运行结果

完整demo下载:https://files.cnblogs.com/files/LikeHeart/ExampleReflection.zip

(完)

反射实现Model修改前后的内容对比的更多相关文章

  1. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  2. Charles系列三:Charles打断点(包含修改请求,修改返回的内容),模拟慢速网络(弱网测试),域名映射,过滤请求,接口调试,打压测试

    一:Charles断点的使用(包含修改请求,修改返回的数据) 设置断点来修改请求和返回的数据,在开发过程中可以模拟多种响应.步骤如下: 1.添加断点方法有两种: 方法1:找到Charles中菜单项Pr ...

  3. 修改placeholder提示内容的颜色以及文本框输入文字内容的颜色

    一般表单文本框提示信息:placeholder=" ",默认颜色是灰色的,输入文本信息也是默认为黑色的,如图所示: 修改placeholder提示内容的颜色关键代码及实现: 实现输 ...

  4. ios UIWebView截获html并修改便签内容(转载)

    ios UIWebView截获html并修改便签内容 博客分类: iphone开发iphone开发phoneGap uiwebviewstringByEvaluatingJavaScriptFromS ...

  5. IOS UIWebView截获html并修改便签内容,宽度自适应

    需求:混合应用UIWebView打开html后,UIWebView有左右滚动条,要去掉左右滚动效果:  方法:通过js截获UIWebView中的html,然后修改html标签内容:  实例代码:  服 ...

  6. ios UIWebView截获html并修改便签内容

    需求:混合应用UIWebView打开html后,UIWebView有左右滚动条,要去掉左右滚动效果: 方法:通过js截获UIWebView中的html,然后修改html标签内容: 实例代码: 服务器端 ...

  7. Mac下显示隐藏文件 以及修改 hosts文件内容

    修改hosts 文件内容: 进入etc 文件夹,找到hosts 文件,把该文件复制出来,修改完里面的内容后,先把etc中的hosts 文件删除,然后在把修改后的文件脱机去 可能需要管理员的密码,你输入 ...

  8. 简单的爬虫爬的完整的<img>标签,修改正则即可修改爬取内容

    简单的爬虫爬的完整的<img>标签,生成<img>标签结果文件与爬虫经历的网页. <?php/** 从给定的url获取html内容** */function _getUr ...

  9. OpenXml修改word特定内容

    采用OpenXml来修改word特定内容,如下: word: OpenXml修改word之前: OpenXml修改word之后: 代码: string path = @"C:\Users\A ...

随机推荐

  1. 深入探索AngularJS

    目录 深入探索AngularJS 作用域Scope是DOM和Directives交互的抽象 Scope是POJO对象 Scope是上下文 Scope继承树 Scope附加功能 正交功能 Element ...

  2. HttpWebRequest 跳转后(301,302)ResponseUri乱码问题

    问题: 目标地址: http://www.baidu.com/baidu.php?url=a000000aa.7D_ifdr1XkSUzuBz3rd2ccvp2mFoJ3rOUsnx8OdxeOeOL ...

  3. DS博客作业03—栈和队列

    1.本周学习总结 本周学习了栈和队列两种数据结构,分别对应后进先出,先进先出两种数据操作 学会栈的特殊类型-共享栈,队列的特殊类型-循环队列的一系列操作 学会熟练使用栈和队列的STL容器,使代码简洁 ...

  4. 【文文殿下】 [USACO08MAR]土地征用 题解

    题解 斜率优化裸题. 有个很玄学的事情,就是我用\(f[i]=min\{f[j-1]+p[j].y*p[i].x\}\) 会很奇怪的Wa . 明明和\(f[i]=min\{f[j]+p[j+1].y* ...

  5. Akka(20): Stream:异步运算,压力缓冲-Async, batching backpressure and buffering

    akka-stream原则上是一种推式(push-model)的数据流.push-model和pull-model的区别在于它们解决问题倾向性:push模式面向高效的数据流下游(fast-downst ...

  6. 基于iview的后台管理

    年前由于时间紧迫,原本使用iview技术开发后台管理系统的大神另有任务,我中途接手该项目,此前对于iview一无所知的我是一脸的懵逼,好在后台管理的整体框架大神已经搭建好了,而我之前对vue也有一定的 ...

  7. 开发ASP.NET MVC 开发名片二维码生成工具 (原创)

    在网上找了很多,都只能生成网址,不能生成名片二维码,于是自己动手. 第一步,写视图界面,主要代码如下: <script type="text/javascript"> ...

  8. 初识java java的加载与执行(JDK,JVM,JRE关系解释)

    首先java代码是以 .java结尾的文件,通过javac命令编译生成.class编译生成字节码文件,再通过java命令,把字节码文件加载到内存内部,此时是类加载器ClassLoader执行加载,通过 ...

  9. POJ 2887

    #include <iostream> #include <string> #define MAXN 2000 using namespace std; struct node ...

  10. django操作memcached

    1.首先需要在settings.py中配置好缓存 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.Me ...