反射实现Model修改前后的内容对比
在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责。
首先我们要创建一个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 = "25", 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(0, SeekOrigin.Begin); 15 retval = xml.Deserialize(ms); 16 ms.Close(); 17 } 18 return (T)retval; 19 }
接下来的工作是修改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这个方法
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
(完)