zoukankan      html  css  js  c++  java
  • 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);
                                }
                            }
                        }
                    }
                }
                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);
            }

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

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

  • 相关阅读:
    [转]SVN服务器搭建和使用(二)
    [转]SVN服务器搭建和使用(一)
    BZOJ 2049 Sdoi2008 Cave 洞穴勘测
    BZOJ 1589 Usaco2008 Dec Trick or Treat on the Farm 采集糖果
    BZOJ 2796 POI2012 Fibonacci Representation
    BZOJ 2115 Wc2011 Xor
    BZOJ 3105 CQOI2013 新Nim游戏
    BZOJ 2460 Beijing2011 元素
    BZOJ 3687 简单题
    BZOJ 1068 SCOI2008 压缩
  • 原文地址:https://www.cnblogs.com/jizhong/p/4158425.html
Copyright © 2011-2022 走看看