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

原始人版:

        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. 参数*args和**args区别

    #*args(元组)和**args(字典)的区别 def tuple_test(*args): for i in args: print 'hello'+i s=('xuexi','mili') tu ...

  2. 修改hive分区表,在分区列前增加一个字段

    本文主要为了测试,在有数据的分区表中增加新的一个非分区字段后,新数据加入表中是否正常. 原始数据 1;zhangsan 2;zhangsan 3;zhangsan 4;lisi 5;lisi 6;li ...

  3. imshow() displays a white image for a grey image

    Matlab expects images of type double to be in the 0..1 range and images that are uint8 in the 0..255 ...

  4. SSL/TLS协议运行机制

      转载自http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html 互联网的通信安全,建立在SSL/TLS协议之上. 本文简要介绍SSL/TLS协议的运行 ...

  5. RealProxy实现AOP编程(2)

    稍微变化一下!注意区别. Program.cs class Program { static void Main(string[] args) { User user = " }; var ...

  6. JSTL配置

    1.下载jakarta-taglibs-standard-1.1.2.zip(在Weblogic中必须下载1.0版http://jakarta.apache.org/site/downloads/do ...

  7. 各种模板(part 1)

    GCD: int gcd(int a,int b) { ?a:gcd(b,a%b); } 快速幂: void work(int x,int y) //x^y { ; ) { ==) ans=ans*x ...

  8. 【转载】javascript与C#的语法区别

    由于博主不允许的情况下不允许转载,我在这里只放上链接 http://blog.csdn.net/ranlianjie/article/details/2484139

  9. 验证视图状态MAC失败。如果此应用程序由网络场或群集承载,请确保配置指定了相同的validationKey和验证算法(转)

    原文转自:http://www.cnblogs.com/Setme/archive/2012/06/05/2537084.html 验证视图状态 MAC 失败.如果此应用程序由网络场或群集承载,请确保 ...

  10. Ubuntu14.04+Beanstalkd1.9最佳实践

    目录 [TOC] 1.基本概念 1.1.什么是Beanstalkd?   Beanstalkd 是一个轻量级消息中间件,它最大特点是将自己定位为基于管道 (tube) 和任务 (job) 的工作队列. ...