做基本数据设定窗体,本以为实现这个小小的窗体应该是最简单的吧!不就是单击修改按钮,进行修改;然后单击更新按钮来对数据基本设定进行更新吗?可是当一出手就遇到了问题,数据表中的数据该怎么显示在文本框中呢?这真的一下子难住了自己!不过遇到问题总会有解决的办法。
既然是让实体一个一个返回到文本框中来,那么直接调用实体层应该就可以吧!这样不就可以完美的实现了吗?可是这样最大的缺点则是:以后遇到的控件与数据调用的窗体比比即是,这样不就又重蹈覆辙实现了代码的重复吗?很严重的违背了为了把重复的部分提取出来,方便以后的调用,所以用到了泛型集合。
那么首先分析一下什么情况下使用泛型集合呢?在基本数据设定中,我们想要实现的功能就是将数据表中的信息转换成为一个一个的实体,然后添加到文本框中,所以我们就可以将数据表中的一个一个的实体作为参数传递给泛型类型,进而得到自己想要的。
由于List是ArrayList的泛型等效类,属于动态数组,正好可以满足自己的需求。我们可以讲类型看做一个模板,这样模板中的变体部分就可以被传来的 类名称所代替,从而得到一个新的定义。
在此之前对于实体层的建立是必不可少的,因为创建集合的基础是要有类,然后才能将对象放入集合中。
建立的EntityModel:
'******************************** '说明:泛型集合,完成datatable类型转化为实体类 '作者:霍亚静 '小组:XX '创建日期:2014-07-20 22:28:21 '版本号:V1.00 '******************************** Imports System.Collections.Generic '增加泛型的命名空间,用来管理泛型集合 Imports System.Reflection '加入反射,为了引用 PropertyInfo Public Class EntityHelper '将datatable转化为泛型集合 Public Shared Function converToList(Of T As {New})(ByVal dt As DataTable) As IList(Of T) Dim myList As New List(Of T) '定义最终返回的集合 Dim myType As Type = GetType(T) '得到实体类的类型名 Dim dr As DataRow '定义行集 Dim TmpName As String = String.Empty '定义一个临时变量 '遍历datatable的所有数据行 For Each dr In dt.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 (dt.Columns.Contains(TmpName)) Then '将此属性与datatable李的列名比较,查看datatable是否包含此属性 '判断此属性是否有setter(类) If (pr.CanWrite = False) Then '判断此属性是否可写,如果不可写,跳出此循环 Continue For End If Dim value As Object = dr(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
这样D层就可以直接调用将T_datatable中表集转化成泛型集合
Public Function ReadBasic() As IList(Of Entity.BasicDataEntity) Implements IDAL.IBasicDataDAL.ReadBasic '应该使用泛型集合类型 ''Dim sqlparams As SqlParameter() = {} '声明并实例化参数数组 '调用无参数查询() 'Return clsSqlhelper.Query(strSQL, CommandType.Text) '调用sqlHelper 'Return table '返回查询结果 'Dim mySqlhelper As Ne'w Sqlhelper.sqlhelper '定义查询助手类,上文已经定义 Dim dt As New DataTable '定义查询到的表集 Dim myList As List(Of Entity.BasicDataEntity) '保存转换后的泛型集合 Dim strSQL As String = "select * from T_BasicData " '声明并实例化需要执行的SQL语句 dt = clsSqlhelper.Query(strSQL, CommandType.Text) '执行查询 '将dt转换为泛型集合 myList = EntityHelper.converToList(Of BasicDataEntity)(dt) Return myList '返回一个实体 End Function
其实整个过程也只是调用了一下泛型集合,改变了一下其类型,和datatable的使用过程还是一样的。
Public Function ReadBasic() As IList(Of Entity.BasicDataEntity) '声明并实例化变量InBasic为:调用Factory所返回来的IBasicDataDAL Dim inBasic As IBasicDataDAL = factory.BasicDataDAL() '事先要声明factory的类型,已声明并实例化factory为DataAccess类 '声明并实例化变量ReadB Dim ReadB As IList(Of Entity.BasicDataEntity) ReadB = inBasic.ReadBasic() Return ReadB '返回ReadB这个泛型数组 End Function
这样在U层就可以直接调用其数组,然后显示在文本框中了
Dim ReadB As IList(Of BasicDataEntity) '定义泛型集合 Dim RBasic As New BasicDataBLL '定义一个b层接口 ReadB = RBasic.ReadBasic() txtRate.Text = ReadB(0).Rate txtTmpRate.Text = ReadB(0).TmpRate txtLimitCash.Text = ReadB(0).limitCash txtLeastTime.Text = ReadB(0).leastTime txtPrepareTime.Text = ReadB(0).prepareTime txtUnitTime.Text = ReadB(0).unitTime
注:
其实做完之后,突然又觉得T_datatable中只是存在一条数据,如果仅仅只是来查询一条数据的话,或许直接调用实体层会更简单一点,又比如登陆窗体,当然也可以直接调用泛型集合,但是对此也只是想查询对应的用户名和密码,仅此而已!如果单单的是一个窗体的话,真的是感觉有点大材小用啊!就好像一个大大的水缸,你偏偏在里边放一升的水,那是不是多此一举呢?还不如直接拿一个小小的水杯盛放,来得更直接一些。
在此使用泛型集合,一是想熟悉一下,再者,整个系统需要用到泛型集合的地方有很多,这里也只是调用了一下公共的部分,减少了重复的代码,又何乐而不为呢?