首页 > 代码库 > C#中Dynamic的妙用及代码重构
C#中Dynamic的妙用及代码重构
应用场景:检查几个表的特定字段是否为空,字段是否为空是在数据库中进行配置的。前台根据数据中字段的设置,进行动态检查。
原始人版:
private string CheckFieldNull(MONTHINPUTDATA data,IList<ReportTemplate> shownFields) { IList<string> result = new List<string>(); if (data.UT_003 != null) { var dataObj = data.UT_003; for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_","") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object o = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (o == null) { result.Add(fs[j].FIELDNAME); } } } } } if (data.UT_012 != null) { var dataObj = data.UT_012; for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object o = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (o == null) { result.Add(fs[j].FIELDNAME); } } } } } if (data.UT_040 != null) { var dataObj = data.UT_040; for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object o = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (o == null) { result.Add(fs[j].FIELDNAME); } } } } } if (data.UT_041 != null) { var dataObj = data.UT_041; for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object o = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (o == null) { result.Add(fs[j].FIELDNAME); } } } } } if (data.UT_042 != null) { var dataObj = data.UT_042; for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object o = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (o == null) { result.Add(fs[j].FIELDNAME); } } } } } return string.Join(",",result); }
这样的代码确实让人纠结。的确,开发者可以几乎不用动脑子,以比较快速度编码(完成一段后,复制、粘贴即可搞定),完成任务。这种编码有一定的灵活性,具体来说就是检查的字段设置(字段由需要检查,变更为不需要检查或者相反)修改后,代码不用变就可以满足要求。不足之处在于有大量的重复代码,而且还应用了硬编码。假如又增加了需要判断的字段表,那么此方法必须修改才行。而且这种写法的代码量很大,也不利于后期维护。总体来说这样的代码质量比较差劲。
OK,既然C# 4.0引入了dynamic,那么我们不妨用此技术简化下代码,于是,就有了第二版的代码,代码如下:
private string CheckFieldNull(MONTHINPUTDATA data,IList<ReportTemplate> shownFields) { IList<string> result = new List<string>(); if (data.UT_003 != null) { var dataObj = data.UT_003; string checkResult = CheckSingleFieldNull(dataObj, shownFields); if (checkResult.Length > 0) { result.Add(checkResult); } } if (data.UT_012 != null) { var dataObj = data.UT_012; string checkResult = CheckSingleFieldNull(dataObj, shownFields); if (checkResult.Length > 0) { result.Add(checkResult); } } if (data.UT_040 != null) { var dataObj = data.UT_040; string checkResult = CheckSingleFieldNull(dataObj, shownFields); if (checkResult.Length > 0) { result.Add(checkResult); } } if (data.UT_041 != null) { var dataObj = data.UT_041; string checkResult = CheckSingleFieldNull(dataObj, shownFields); if (checkResult.Length > 0) { result.Add(checkResult); } } if (data.UT_042 != null) { var dataObj = data.UT_042; string checkResult = CheckSingleFieldNull(dataObj, shownFields); if (checkResult.Length > 0) { result.Add(checkResult); } } return string.Join(",",result); } private string CheckSingleFieldNull(dynamic dataObj, IList<ReportTemplate> shownFields) { for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object fv = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (fv == null) { return fs[j].FIELDNAME; } } } } return string.Empty; }
这样一来,将检查部分抽出来,提炼成一个函数,需要判断的地方进行判断,这样修改下来,代码确实精简了很多,但是....,似乎代码量还是很大,并且还没有解决硬编码(枚举表名)的问题。既然我们是冲着dynamic去的,那么我们不妨再做的彻底些,于是第三版趁着热乎劲出炉了。
private string CheckFieldNull(MONTHINPUTDATA data, IList<ReportTemplate> shownFields) { IList<string> result = new List<string>(); Type Ts = data.GetType(); for (var i = 0; i < shownFields.Count; i++) { var tn = shownFields[i].code.CODEVALUE; dynamic fv = Ts.GetProperty(tn).GetValue(data, null); if (fv == null) { result.Add(shownFields[i].code.CODENAME); continue; } string checkResult = CheckSingleFieldNull(fv, shownFields); if (checkResult.Length > 0) { result.Add(checkResult); } } return string.Join(",", result); } private string CheckSingleFieldNull(dynamic dataObj, IList<ReportTemplate> shownFields) { for (var i = 0; i < shownFields.Count; i++) { var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf(‘.‘) + 1); if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName) { var fs = shownFields[i].FieldList; Type Ts = dataObj.GetType(); for (var j = 0; j < fs.Count; j++) { object fv = Ts.GetProperty(fs[j].FIELDNO).GetValue(dataObj, null); if (fv == null) { return fs[j].FIELDNAME; } } } } return string.Empty; }
这样一来,完全达到了动态检查字段为空的目的,不再硬编码,完全听命于数据库中有关字段的配置。至此,再无纷扰,天下太平了。
备注:请无视示例代码中函数的参数命名及函数内变量的命名方式(纯粹展示用)。
C#中Dynamic的妙用及代码重构
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。