科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航



ZDNet>软件频道>中间件-zhiding>VB中运用反射原理优化程序代码

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在这个项目里我负责的部分是读取某子系统从数据库导出来的两个XML(不妨假设为A.XML和B.XML)文件并根据文件内容完成本部分的业务工作流程

来源:天极开发 2007年10月14日

关键字:程序代码 优化 反射 VB

在这个项目里我负责的部分是读取某子系统从数据库导出来的两个XML(不妨假设为A.XML和B.XML)文件并根据文件内容完成本部分的业务工作流程。文件是以共享方式放在服务器上,我只需要获得一个Session访问即可,因为要求是实时读写文件,所以否定了下载到本地进行读写的方法,而为了保证程序生命力和数据的完整性,我决定将文件信息一次性读入程序存储空间,并在业务流程中设定当完成某个特定的步骤后回写一遍AB两文件,其中A文件节点可能有增删B文件只是更新某个标志。

  一开始设计具体类的时候很容易想到构造和文件结构对应的类,使用庞大的DOM对象?哦,我可不需要那么多累赘。现在我把对应AB两文件的类分别写了个大概出来,很简单如下:

Class clsA/B
Property Name1 as string
 ...
End Property
Property Name2 as string
 ...
End Property
 ......
 ......
 ......
End Class

  A,B各需要要一个集合类管理,分别命名为clscolA,clscolB,大概如下:

Public Class clscolA/B
Inherits System.Collections.CollectionBase
Public Function GenerateAson() As clsA/clsB
 'New并返回一个 clsA or clsB
 '初始化属性的工作可以在这里进行
End Function
Public Sub AddSon(ByVal objSon As clsA/clsB)
 '增加一条新纪录
 InnerList.Add(objSon)
End Sub
Public Sub Sort()
 '根据某设定的属性对集合进行排序
 InnerList.Sort(New clsSortByName)
End Sub
'默认Item属性以及更多Method从略
End Class

  好了,现在程序数据的基本框架搭好了,这无疑是十分中庸地解决办法,当然也是十分有效的,本文的主题并不是特别愿意删减这些成熟的代码(当然也仅仅是暂且不动而已)。躯壳已有,剩下的工作就是从文件读取并填充数据,如果你还没有接触过反射或者仅仅限于书本上那点例子,这对你来说可能是一个简单而又枯燥的过程,你于是乎也条件反射似地写起来
New一个clscolA/B(就叫colA/B吧)然后遍历文件或取一个包含所有记录(目标节点)的NodeList,然后作如下状:

With NodeList
 for i as integer=0 to .Count-1
  Dim objson as clsA/B=colA/B.GenerateAson
  objson.Name1=.item(i).childnodes(x1).innertext
  objson.Name2=.item(i).childnodes(x2).innertext
  ......
  ......
  ......
  colA/B.Addson(objson)
 next i
End With

  这段代码虽然他够用,又看似天衣无缝,但总觉得不对头,当属性达到一定数量,你有没有发现你将会使用了太多的同样的赋值句?小学语文就告诉过我们适当使用排比句可以为文章造势,但是如果你一口气排比了20条,那就是滥用了,笔者这里A文件每一条记录有三十多个Field,B文件也有十多个,如果这样用下来景象肯定巍巍壮观,先估计一下代码量,A文件每条记录按30个Field,B按15个算,赋值过程便是45行,还不包括格式化处理和排错处理,如果考虑程序扩展性,以后要读更多的文件则必然会伴随更多类似的过程出现,写程序和做人一样,要低调,一定要低调啊,有激情的程序员自然不会如此糟蹋自己的代码,是否能用一个函数或过程解决上述问题呢?新方案应用而生,采用反射(Imports/using System.Reflection),一个通用过程解决所有问题。示例函数如下:

Public Shared Function FillFromXml(ByVal NodeName As String, ByVal strPath As String, ByVal objFather As Object) As Boolean
 Try
  With xmlGetList(NodeName, strPath)
   For i As Integer = 0 To .Count - 1
    Dim st As Object = objFather.GenerateAson
    Dim ty As Type = st.GetType
    For Each pp As PropertyInfo In ty.GetProperties
     With DirectCast(.Item(i), XmlElement)
      If .SelectSingleNode(pp.Name.ToUpper) IsNot Nothing Then
       pp.SetValue(st, CType(.SelectSingleNode(pp.Name.ToUpper).InnerText.Trim, String), Nothing)
      End If
     End With
    Next
    objFather.AddSon(st)
   Next
  End With
  Return True
 Catch ex As Exception
  Return False
 End Try
End Function

  使用这个函数,只需要保证集合类clscolA/B有GenerateAson和Addson两个方法以及clsA/B两子类的属性名称与文件中Field保持一致即可。你只需要传递相应A或者B文件的目标节点名,文件路径,以及对应的集合类即可,此时再看一下赋值过程的代码减少了多少,恩,只有8行,这对于笔者则意味着省去了45-8=37行代码,而且丢弃老套的排比句。

  第一阶段战斗算是小试牛刀了一把,如果只算赋值过程代码减少百分数为37/45,接近83%。

你也可能抱怨我上面的百分数计算太不科学,要算也应该拿全部来算,那就不妙了,好吧,看来也只能拿十分“老的““成熟“的来开刀了,下面便是削减代码二期工程,我们的目标是让成熟变干练,太过成熟的确不合某些同志的胃口。对应于AB两文件的类clsA/B,分别至少有30和15个属性,还好,也不过就一二百行代码就搞定,更简单点就用自己写的代码生成器,一次性生成所有属性,并不会很麻烦。不过还是有更好(准确使更精简)的解决办法,用一个通用类,十分之一的代码(实际应用中会更少)就可以做到。

  这其实不过是一个继承了字典的子类,如下:

Public Class clsCommon
 Inherits System.Collections.DictionaryBase
 Public Sub AddField(ByVal FieldName As String, ByVal value As Object)
 Dictionary.Add(FieldName, value)
End Sub

Default Public Property Item(ByVal key As String) As Object
 Get
  Return Dictionary.Item(key)
 End Get
 Set(ByVal value As Object)
  Dictionary.Item(key) = value
 End Set
End Property
End Class

  这个通用类提供两个基本的方法,意义显而易见,而其对应的集合类基本还是原来那个样子:

Public Class clscolCommon
 Inherits System.Collections.CollectionBase
 Public Function GenerateAson() As clsCommon
End Function

Public Sub AddSon(ByVal objSon As clsCommon)
End Sub
Public Sub Sort()
End Sub
'默认Item属性以及更多Method从略
End Class

  不过这时候赋值过程也需要更改一下:

With xmlGetList(NodeName, strPath)
 For i As Integer = 0 To .Count - 1
  Dim st As Object = objFather.GenerateAson
  With DirectCast(.Item(i), XmlElement)
   For Each ch As XmlNode In .ChildNodes
    St.AddField(ch.Name,ch.InnerText)
   Next
  End With
  objFather.AddSon(st)
 Next
End With

  本文至此,削减代码工程算是小有成就,如果真要计算削减了多少,我想还是能够对得起这个标题的,而关于如何回写文件,必然也仍然是反射,肯定有更好的办法,在这里就不赘述了。

 

查看本文来源

推广二维码
邮件订阅

如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

重磅专题