接上一篇文章---从SqlHelper到泛型集合(1)。
师傅说了,机房重构只允许返回三种类型的值:Boolean,实体,泛型集合。不允许返回DataTable,就想方设法把DataTable转换成实体和泛型集合。当返回一条记录时,可以将DataTable转换成实体;返回多条记录的时呢?总不能一条一条通过实体返回吧?
由此,开始了我的泛型集合之旅。
听到“泛型集合”这个词的时候,我突然想到了《大话设计模式》附录上的泛型,重写阅读此内容,发现了“泛型集合”的身影。
参照《大话设计模式》上的例子和一些相关知识,不难写出泛型集合。如下:
<span style="font-size:18px;">Imports System.Collections.Generic '增加泛型的命名空间
Imports System.Reflection '引入反射,为了引用PropertyInfo
Public Class EntitySetGeneric
'将DataTable转换成泛型集合
Public Shared Function ConvertToList(Of T As {New})(ByVal dataTable As DataTable) As IList(Of T)
'ConvertToList(Of T As {New}) 这里的New是用来约束T的,必须有,不然New T的时候会出现错误
Dim myList As New List(Of T) '定义最终返回的集合
Dim myType As Type = GetType(T) '得到实体类的类型名
Dim dataRow As DataRow '定义行集
Dim TmpName As String = String.Empty '定义一个临时变量
'遍历DataTable的所有数据行
For Each dataRow In dataTable.Rows
Dim myT As New T '定义一个实体类的对象
Dim propertys() As PropertyInfo = myT.GetType().GetProperties() '定义属性集合
Dim pr As PropertyInfo
'遍历该对象的所有属性
For Each pr In propertys
TmpName = pr.Name '将属性名称赋值给临时变量
'检查DataTable是否包含此列(列名==对象的属性名)
If (dataTable.Columns.Contains(TmpName)) Then '将此属性与DataTable里的列名比较,查看DataTable是否包含此属性
'判断此属性是否有Setter(类)
If (pr.CanWrite = False) Then '判断此属性是否可写,如果不可写,跳出本次循环,进入下一次循环;exit for 是退出整个循环
Continue For
End If
Dim value As Object = dataRow(TmpName) '定义一个对象型的变量来保存列的值
If (value.ToString <> DBNull.Value.ToString()) Then '如果非空,则赋给对象的属性
pr.SetValue(myT, value, Nothing) '在运行期间,通过发射,动态地访问一个对象的属性
End If
End If
Next
myList.Add(myT) '添加到集合
Next
Return myList '返回实体集合
End Function
End Class
</span>
泛型集合没有确定的类型,但在使用前必须规定类型。泛型集合大大简化了集合的实现代码,通过它,可以轻松创建指定类型的集合。恰当的运用泛型集合,可以减少很多重复工作,极大的提高开发效率。