• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

C#中Dynamic的妙用及代码重构

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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

原始人版:

        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);
                            }
                        }
                    }
                }
            }
            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);
                }
            }
            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 inputDataType = data.GetType();
            for (var i = 0; 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 > 0)
                {
                    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 = 0; 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);
        }

 

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

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

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap