数据模型类对比,用反射做个快乐的程序员

作者在开发人才管理系统操作日志记录功能时,面临字段对比难题。最初考虑两种方案,最终选择存储新旧Model对比。为避免逐个字段对比,采用反射,后结合泛型提高代码复用性。还利用特性解决英文显示问题,最后对数据实体外键字段显示问题寻求解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  曾经看《大话设计模式》的时候说到 反射反射程序员的欢乐,当时我还不太相信 毕竟自己不太会反射。甚至什么时候用反射我也不太知道,只能说查了些资料知道有一些反射这咱东西仅此而已。

  这几天在做一个人才管理系统,其中有一个让我纠结的就是 操作日志这块吧,特别是在修改的时候要记录每个字段改变前后的情况。好吧,当时有两个决定方案吧。一、再建了一张和原表相同的结构的呗,再用一个外键和原表主键连下,做下记录吧。二、就是在读取数据的时候存储两个Model,一个New Model 一个Old Model呗,然后再对比下。

  最后,由于种种的原因选择了第二次方式。好吧,竟然用第二种说出来一个问题,怎么对比两个Model来,难道一个个字段对比吗?天哪这不噩梦嘛,如果有20个字段我不是要写20多个对比 20多个IF了,这我不干 这明显就不是最良的代码好,不过我也没什么好的办法 只能问问度娘、GOOOGLE呗,在这个互联网的时代,要善用搜索引擎嘛,于是找了下。

一开始代码应该是这样的。有两个实体变量,存放的是修改前和修改后的信息。比如:

InfoModel oldModel=new InfoModel();

InfoModel newModel=new InfoModel();

需要遍历这两个实体类的全部属性的值来进行对比,并将有差别的列出来。

  找到一个解决的方案就是使用反射进行对比

//反射遍历
System.Reflection.PropertyInfo[] mPi = typeof(InfoModel).GetProperties();


                for (int i = 0; i < mPi.Length; i++)
                {
                    System.Reflection.PropertyInfo pi = mPi[i];

                    oldValue = pi.GetValue(oldModel, null).ToString();
                    newValue = pi.GetValue(newModel, null).ToString();
                    if (oldValue !=newValue )
                    {
                         有差别的列出来
                    }
                 }

}
View Code

  在这里,用一个小问题那就是typeOf是用来放是哪个 MODEL的嘛!还有就是这是什么 oldModel,newModel,如果向这么不就写死了嘛,每比较一个数据模型类不是都要这样写一个方法不是很麻烦,这以前那个对比虽然好了些不会用这么多的IF了 可是还是不能复用的嘛,只知道做软件设计的做到啥 可维护、可复用、可扩展、灵活性好。

   好吧,这个明显不能复用的嘛。改改呗,最好做到的就是所有的类都可以用这个方法,此时脑子里瞬间就想起了 泛型。【泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。 泛型通常用与集合以及作用于集合的方法一起使用。 .NET Framework 2.0 版类库提供一个新的命名空间 System.Collections.Generic,其中包含几个新的基于泛型的集合类。泛型是 C# 2.0 的最强大的功能。通过泛型可以定义类型安全的数据结构,而无须使用实际的数据类型。这能够显著提高性能并得到更高质量的代码,因为您可以重用数据处理算法,而无须复制类型特定的代码。在概念上,泛型类似于 C++ 模板,但是在实现和功能方面存在明显差异。】这是从MSDN对泛型的介绍,好吧,我想这个功能应该可以满足我的要求,把代码改改呗

 1   public string CompareModel<T>(T newModel, T oldModel)  
 2         {
 3             StringBuilder strLog = new StringBuilder();
 4             System.Reflection.PropertyInfo[] mPi = typeof(T).GetProperties();
 5             for (int i = 0; i < mPi.Length; i++)
 6             {
 7                 System.Reflection.PropertyInfo pi = mPi[i];
 8                 string strName = string.Empty;
 9                 string log = string.Empty;
10                 if (pi.GetValue(oldModel, null) != null && pi.GetValue(newModel, null) != null)
11                 {
12                     string name = pi.Name;//字段名
13                     string oldValue = pi.GetValue(oldModel, null).ToString();//获取对应字段的值
14                     string newValue = pi.GetValue(newModel, null).ToString();
15                     if (oldValue != newValue)
16                     {//具体差异的操作
17                         strLog.AppendFormat("{0}从{1}改为{2}", name, oldValue, newValue);
18                     }
19                 }
20             }
21             return strLog.ToString();
22         }
View Code

  这样也可以一一的不同的数据列出来了,可这里还有一个问题就是其中的NAME是英文的啊,总不可能给客户看英文的吧,再想想办法呗。在这里看到 PropertyInfo 有个GetCustomAttributes 的方面,这不就是可以获取特性的方法嘛,特性我知道就啊,就想在MVC中Model类里的字段上前的 [Display(Name = "用户名")] 这种东东嘛,好吧,我也有这个样的吧,虽然Attributes 是可以自定义的,但我还是小小的懒下使用MVC里的算了,自己写也太麻烦,自己本身对这个也不太会用嘛,只能算是拿来主义。开心的引用了using System.ComponentModel.DataAnnotations;

 1 using System;
 2 using System.ComponentModel.DataAnnotations;
 3 
 4  public class LoginModel
 5     {
 6        
 7         [Display(Name = "用户名")]
 8         public string UserName { get; set; }
 9 
10         public string ExternalLoginData { get; set; }
11     }
12  /// <summary>
13         /// 说明:对比实体类
14         /// 时间:2014年2月20日 14:17:48
15         /// Auhter:Kim
16         /// </summary>
17         /// <typeparam name="T"></typeparam>
18         /// <param name="newModel"></param>
19         /// <param name="oldModel"></param>
20         /// <returns></returns>
21         public string CompareModel<T>(T newModel, T oldModel) where T : class,new ()
22         {
23             StringBuilder strLog = new StringBuilder();
24             System.Reflection. PropertyInfo[] mPi = typeof(T).GetProperties();
25             for (int i = 0; i < mPi.Length; i++)
26             {
27                 System.Reflection. PropertyInfo pi = mPi[i];
28                 string strName = string .Empty;
29                 string log=string .Empty;
30                 if (pi.GetValue(oldModel, null ) != null && pi.GetValue(newModel, null ) != null)
31                 {
32 
33                     strName = Attributes.GetDisplayInfo<T>(pi.Name);
34                     string oldValue = pi.GetValue(oldModel, null).ToString();
35                     string newValue = pi.GetValue(newModel, null).ToString();
36                     if (oldValue != newValue)
37                     {
38                         if (GetNameByDictonary(strName, oldValue, newValue, out log))
39                             strLog.Append(log);
40                         else
41                             strLog.AppendFormat("<strong>{0}</strong><span>{0} 从 {1} 改为 {2}</span>&nbsp;&nbsp;", strName, oldValue, newValue);
42                     }
43                 }
44             }
45             return strLog.ToString();
46         }
47 
48 
49 /// <summary>
50         /// 获取DisplayInfo
51         /// </summary>
52         /// <param name="t"></param>
53         public static string GetDisplayInfo<T>( string name) where T : class,new ()
54         {
55             Type objType = typeof (T);
56             // Using reflection.
57             string strName = string .Empty;
58             PropertyInfo propInfo = objType.GetProperty(name);
59             object[] attrs = propInfo.GetCustomAttributes(typeof (DisplayAttribute), true);  // Reflection.
60             // Displaying output.
61             if (attrs.Length > 0)
62             {
63                 DisplayAttribute a = attrs[0] as DisplayAttribute;
64                 strName = a.Name;
65             }
66 
67             return strName;
68         }
View Code

 

这样的代码也基本的符合要求了,不过小弟在这还有一个不解的地方就是说,有一些数据实体类型的字段是别的表的外键嘛,这又要怎么正常在的数据显示出来哪?希望各位大神 指导一二,各位码农、码友们有些好的解决方案 也探讨下呗,提出你们的宝贵意见,小弟先在这里谢过了!  

                                              

 

转载于:https://www.cnblogs.com/chenmoit/p/3561922.html

内容概要:本文详细介绍了扫描单分子定位显微镜(scanSMLM)技术及其在三维超分辨体积成像中的应用。scanSMLM通过电调透镜(ETL)实现快速轴向扫描,结合4f检测系统将不同焦平面的荧光信号聚焦到固定成像面,从而实现快速、大视场的三维超分辨成像。文章不仅涵盖了系统硬件的设计与实现,还提供了详细的软件代码实现,包括ETL控制、3D样本模拟、体积扫描、单分子定位、3D重建和分子聚分析等功能。此外,文章还比较了循环扫描与常规扫描模式,展示了前者在光漂白效应上的优势,并通过荧光珠校准、肌动蛋白丝、线粒体网络和流感A病毒血凝素(HA)蛋白聚的三维成像实验,验证了系统的性能和应用潜力。最后,文章深入探讨了HA蛋白聚与病毒感染的关系,模拟了24小时内HA聚的动态变化,提供了从分子到细胞尺度的多尺度分析能力。 适合人群:具备生物学、物理学或工程学背景,对超分辨显微成像技术感兴趣的科研人员,尤其是从事细胞生物学、病毒学或光学成像研究的科学家和技术人员。 使用场景及目标:①理解和掌握scanSMLM技术的工作原理及其在三维超分辨成像中的应用;②学习如何通过Python代码实现完整的scanSMLM系统,包括硬件控制、图像采集、3D重建和数据分析;③应用于单分子水平研究细胞内结构和动态过程,如病毒入侵机制、蛋白质聚等。 其他说明:本文提供的代码不仅实现了scanSMLM系统的完整工作流程,还涵盖了多种超分辨成像技术的模拟和比较,如STED、GSDIM等。此外,文章还强调了系统在硬件改动小、成像速度快等方面的优势,为研究人员提供了从理论到实践的全面指导。
内容概要:本文详细介绍了基于Seggiani提出的渣层计算模型,针对Prenflo气流床气化炉中炉渣的积累和流动进行了模拟。模型不仅集成了三维代码以提供气化炉内部的温度和浓度分布,还探讨了操作条件变化对炉渣行为的影响。文章通过Python代码实现了模型的核心功能,包括炉渣粘度模型、流动速率计算、厚度更新、与三维模型的集成以及可视化展示。此外,还扩展了模型以考虑炉渣组成对特性的影响,并引入了Bingham流体模型,更精确地描述了含未溶解颗粒的熔渣流动。最后,通过实例展示了氧气-蒸汽流量增加2%时的动态响应,分析了温度、流动特性和渣层分布的变化。 适合人群:从事煤气化技术研究的专业人士、化工过程模拟工程师、以及对工业气化炉操作优化感兴趣的科研人员。 使用场景及目标:①评估不同操作条件下气化炉内炉渣的行为变化;②预测并优化气化炉的操作参数(如温度、氧煤比等),以防止炉渣堵塞;③为工业气化炉的设计和操作提供理论支持和技术指导。 其他说明:该模型的实现基于理论公式和经验数据,为确保模型准确性,实际应用中需要根据具体气化炉的数据进行参数校准。模型还考虑了多个物理场的耦合,包括质量、动量和能量守恒方程,能够模拟不同操作条件下的渣层演变。此外,提供了稳态求解器和动态模拟工具,可用于扰动测试和工业应用案例分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值