应用场景:检查几个表的特定字段是否为空,字段是否为空是在数据库中进行配置的。前台根据数据中字段的设置,进行动态检查。

原始人版:

        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 = ; i < shownFields.Count; i++)
{
var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf('.') + );
if (shownFields[i].code.CODEVALUE.Replace("_","") == objName)
{
var fs = shownFields[i].FieldList;
Type Ts = dataObj.GetType();
for (var j = ; 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 = ; i < shownFields.Count; i++)
{
var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf('.') + );
if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName)
{
var fs = shownFields[i].FieldList;
Type Ts = dataObj.GetType();
for (var j = ; 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 > )
{
result.Add(checkResult);
}
}
if (data.UT_012 != null)
{
var dataObj = data.UT_012;
string checkResult = CheckSingleFieldNull(dataObj, shownFields);
if (checkResult.Length > )
{
result.Add(checkResult);
}
}
return string.Join(",",result);
} private string CheckSingleFieldNull(dynamic dataObj, IList<ReportTemplate> shownFields)
{
for (var i = ; i < shownFields.Count; i++)
{
var objName = dataObj.ToString().Substring(dataObj.ToString().LastIndexOf('.') + );
if (shownFields[i].code.CODEVALUE.Replace("_", "") == objName)
{
var fs = shownFields[i].FieldList;
Type Ts = dataObj.GetType();
for (var j = ; 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 inputDataType = data.GetType();
for (var i = ; i < shownFields.Count; i++)
{
var fieldNo = shownFields[i].code.CODEVALUE; dynamic fieldValue = inputDataType.GetProperty(fieldNo).GetValue(data, null); if (fieldValue == null)
{
result.Add(shownFields[i].code.CODENAME);
continue;
} string checkResult = CheckSingleTableFieldNull(fieldValue, shownFields[i].FieldList); if (checkResult.Length > )
{
result.Add(checkResult);
}
}
return string.Join(",", result);
} private string CheckSingleTableFieldNull(dynamic field, IList<UVQYJYPERIODREPORT> shownFields)
{
Type inputDataType = field.GetType(); IList<string> result = new List<string>(); for (var i = ; i < shownFields.Count; i++)
{
//字段为目录级别时,不需要判断。
if (shownFields[i].ISDIRECTORY == field_IsDirectory) { continue; } object fieldValue = inputDataType.GetProperty(shownFields[i].FIELDNO).GetValue(field, null); if (fieldValue == null)
{
result.Add(shownFields[i].FIELDNAME);
}
}
return string.Join(",", result);
}

这样一来,完全达到了动态检查字段为空的目的,不再硬编码,完全听命于数据库中有关字段的配置。至此,再无纷扰,天下太平了。

备注:请无视示例代码中函数的参数命名及函数内变量的命名方式(纯粹展示用)。

C#中Dynamic的妙用及代码重构的更多相关文章

  1. Android Studio在代码重构中的妙用

    代码重构几乎是每个程序员在软件开发中必须要不断去做的事情,以此来不断提高代码的质量.Android Stido(以下简称AS)以其强大的功能,成为当下Android开发工程师最受欢迎的开发工具,也是A ...

  2. C#中dynamic的正确用法

    C#中dynamic的正确用法  http://www.cnblogs.com/qiuweiguo/archive/2011/08/03/2125982.html dynamic是FrameWork4 ...

  3. C#中dynamic的正确用法 以及 typeof(DynamicSample).GetMethod("Add");

    dynamic是FrameWork4.0的新特性.dynamic的出现让C#具有了弱语言类型的特性.编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性.比如,即使你 ...

  4. C#中dynamic、ExpandoObject 的正确用法

    原文地址:http://www.cnblogs.com/qiuweiguo/archive/2011/08/03/2125982.html dynamic是FrameWork4.0的新特性.dynam ...

  5. C#中dynamic的正确用法【转】

    dynamic是FrameWork4.0的新特性.dynamic的出现让C#具有了弱语言类型的特性.编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性.比如,即使你 ...

  6. 【转】C#中dynamic的正确用法

    原文:http://www.cnblogs.com/qiuweiguo/archive/2011/08/03/2125982.html dynamic是FrameWork4.0的新特性.dynamic ...

  7. 解决C#中dynamic类型作为泛型参数的反射问题

    C#中dynamic类型作为泛型参数传递过去后,反射出来的对象类型是object,我用老外的这篇博文中的代码跑起来,得出的结果是:Flying using a Object map (a map),将 ...

  8. C#开发中使用Npoi操作excel实例代码

    C#开发中使用Npoi操作excel实例代码 出处:西西整理 作者:西西 日期:2012/11/16 9:35:50 [大 中 小] 评论: 0 | 我要发表看法 Npoi 是什么? 1.整个Exce ...

  9. 2.C#中通过委托Func消除重复代码

    阅读目录   一:重复的代码 二:C#中通过委托Func消除重复代码 一:重复代码    public class Persion { public string Name { get; set; } ...

随机推荐

  1. iOS 打电话 发短信(转载)

    官方代码 发短息和邮件添加MessageUI.framework 库 发送信息 - (IBAction)showSMSPicker:(id)sender { // You must check tha ...

  2. download github files

    想要下载github的文件,但是却发现无从下手.发现一个网站DownGit,非常方便,只要贴一下链接即可: https://minhaskamal.github.io/DownGit/#/home

  3. 前端开发薪资之各地区对比(图文分析)(share)

    发现最近大家都在关注有关前端开发的薪资问题,不同地方各有差异,今天我就总结一下发出来方便大家的查阅.(2014年) 前面给大家介绍了关于前端开发需要学习的东西,根据你掌握的技能程度,薪水是不一样的.d ...

  4. 各数据库查询前N条记录的SQL语句

    sql在不同数据库查询前几条数据 1. ORACLE SELECT * FROM TABLE_NAME WHERE ROWNUM <= N;  HQL: from table_name t or ...

  5. 接口 Post

    public static StringBuilder HttpPost(string Url, byte[] Postdata, string i) { StringBuilder content ...

  6. win 7~~~win 10 debug的使用方法

    第一步:下载安装DOSBox软件 附上链接:http://pan.baidu.com/share/link?uk=553724690&shareid=3310971559&third= ...

  7. Roslyn 学习笔记(一)

    本文记录了Roslyn开发环境的安装与编译过程,参考了以下Roslyn项目的官方文档 https://github.com/dotnet/roslyn/blob/master/docs/contrib ...

  8. BZOJ 1303 CQOI2009 中位数图 水题

    1303: [CQOI2009]中位数图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2340  Solved: 1464[Submit][Statu ...

  9. setTimeout的使用与参数传递

        在使用JavaScript的时候,我们有时需要间隔的执行一个方法,比如用来产生网页UI动画特效啥的.这是我们常常会使用方法setInterval或setTimeout,但是由于这两个方法是由脚 ...

  10. Nginx-解读内置非默认模块 ngx_http_stub_status_module

    1.Background ngx_http_stub_status_module 是一个 Nginx 的内置 HTTP 模块,该模块可以提供 Nginx 的状态信息.默认情况下这个模块是不被编译进来的 ...