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

原始人版:

        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. BT协议分析(1)—1.0协议

    简述 BT下载是采用P2P的下载方式,下载的大致形式采用如下图所示,处于图示中心的称为Tracker服务器,其余称为Peer.   缺点 1.资源的安全性 2.资源的实效性(没有上传者则BT也将失效) ...

  2. kafka性能基准测试

    转载请注明出处:http://www.cnblogs.com/xiaodf/ 1.测试环境 该benchmark用到了六台机器,机器配置如下 l  IntelXeon 2.5 GHz processo ...

  3. scrollView中可以自由滚动的listview

    直接在scrollView中写listview等可滚动控件会出现子控件高度计算的问题,为了解决这个问题,找到的方案是重写listview中的onmeasure方法: @Override public ...

  4. IplImage结构体

    一.IplImage的一些重要成员: 1.origin:图像原点的定义.=0,则图片的左上角是原点:=1,则左下角是原点.                                  IplIm ...

  5. CoreData数据库

        一  CoreData 了解 1 CoreData 数据持久化框架是 Cocoa API 的一部分,首先在iOSS5 版本的系统中出现:      它允许按照 实体-属性-值 模式组织数据: ...

  6. Android的Notification使用注意事项

    看<Android开发-第一行代码>这本书,读到创建系统通知(Notification)的时候,发现若干主要方法均已经过期,于是找了一下官方的开发指南,进入此url:http://deve ...

  7. Get Jenkins job build queue length

    Jenkins API doesn’t provide the job build queue length. Hence, it seems we have to parse the html to ...

  8. Monkey工具使用详解

    上节中介绍了Monkey工具使用环境的搭建,传送门..本节我将详细介绍Monkey工具的使用. 一.Monkey测试简介 Monkey测试是Android平台自动化的一种手段,通过Monkey程序模拟 ...

  9. iOS面试题汇总

    摘要:1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通 ...

  10. GROUP与HAVING的使用

    SELECT pub_name, state,SUM(state) AS 总数 FROM publishers GROUP BY pub_name, state HAVING SUM(state)&g ...