一、泛型概念
泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型和器方法的参数类型出现。
二、机房重构中的泛型
我们开始重构时在SQLHelper中返回的是一张表也就是DataTable类型的,然后再一直返回到U层中都是把DataTable当做Model来使用,而我们的Model却被放置在了一边,于是我们的三层结构就被破坏了。现在我们的系统简单返回的是一张表,如果返回的是多张表,一个DataTable够吗?于是泛型应用而生。借用了一张图:
三、数组、集合、泛型
四、代码部分
以学生收取金额为例:
D层代码:
Public Class QueryGetCashDAL : Implements IDAL.QueryGetCashIDAL '实现接口 Public Function QueryGetCashIDAL(GetCash As Entity.QueryGetCash) As List(Of Entity.QueryGetCash) Implements IDAL.QueryGetCashIDAL.QueryGetCashIDAL Dim SqlHelperObject As New SqlHelper.LoginSqlHelper Dim dt As DataTable '定义接受DataTable的dt Dim Sql As String Dim myList As New List(Of Entity.QueryGetCash) '定义接受DataTable转换后List '将实体层字段赋值给参数 Dim SqlParams As SqlParameter() = {New SqlParameter("@StartDate", GetCash.StartDate), New SqlParameter("@EndDate", GetCash.EndDate)} '查询语句 Sql = "select * from T_RechargeInfo where RechargeDate>=@StartDate and RechargeDate<=@EndDate" '传到SQLHelper层,返回内容给dt dt = SqlHelper.LoginSqlHelper.GetDataTable(Sql, CommandType.Text, SqlParams) '判断DataTable表中是否有数据 If (dt.Rows.Count > 0) Then ' 将DataTable转换成泛型 myList = ConvertHelper.ConvertHelper.ConvertToList(dt, myList) Return myList Else Throw New Exception("没有记录!") Return Nothing End If End Function End Class
DataTable转List:
Module ConvertHelper Public Class ConvertHelper Public Shared Function ConvertToList(Of T As {New})(dt As DataTable, ts As IList(Of T)) Dim type As Type = GetType(T) '获得T的类型 Dim strTemp As String = String.Empty '定义一个临时变量 '遍历表中所有行数 For Each dr As DataRow In dt.Rows '定义类型变量act获取动态创建对象T的类型 Dim act As T = If((Nothing Is Nothing), Activator.CreateInstance(Of T)(), Nothing) '引用反射表示可获得对象的所有属性组成的集合 Dim propertys As PropertyInfo() = act.[GetType]().GetProperties() '定义array变量,接收propertys中含有的属性,并提供对属性propertys元数据访问 Dim array As PropertyInfo() = propertys Dim intCount As Integer = 0 '定义计数初始为0 '遍历所有对象属性 While intCount < array.Length 'length表示所有维数中元素的总和 Dim pr As PropertyInfo = array(intCount) 'pr表示元素中含有的属性,并提供对数据访问 strTemp = pr.Name '列名=对象的属性名 If dt.Columns.Contains(strTemp) Then '判断此属性是否设置函数 If pr.CanWrite Then '该属性是否可写 Dim value As Object = dr(strTemp) If value IsNot DBNull.Value Then pr.SetValue(act, value, Nothing) '赋值给对象的属性 End If End If End If intCount += 1 '每条记录中字段+1 Continue While End While '添加对象到泛型集合中 ts.Add(act) Next Return ts End Function End Class End Module
U层中结合DataGridView控件使用:
Try '获得起始终止时间给实体 GetCash.StartDate = StartDate.Text.Trim() GetCash.EndDate = EndDate.Text.Trim() QueryDate = FacadeObject.FacadeQueryGetCash(GetCash) '判断卡号是否存在 If QueryDate.Count = 0 Then MessageBox.Show("卡号不存在", "温馨提示") Else DGQueryGetCash.Rows.Add(QueryDate.Count) '数据表添加行,行数等于数据行数 For i = 0 To QueryDate.Count - 1 '变量写入行上的每个数据,rows代表行,Cell代表第几个格 DGQueryGetCash.Rows(i).Cells(0).Value() = QueryDate(i).CardNo DGQueryGetCash.Rows(i).Cells(1).Value() = QueryDate(i).RechargeCash DGQueryGetCash.Rows(i).Cells(2).Value() = Format(QueryDate(i).RechargeDate) DGQueryGetCash.Rows(i).Cells(3).Value() = QueryDate(i).RechargeTime DGQueryGetCash.Rows(i).Cells(4).Value() = QueryDate(i).UserID DGQueryGetCash.Rows(i).Cells(5).Value() = QueryDate(i).IsCheck Next MessageBox.Show("查询成功", "恭喜您") End If Catch ex As Exception MessageBox.Show(ex.Message.ToString()) End Try
在U层、Facade层、B层以及接口处把返回类型和接收类型改成List
五、LIst优点
从上面例子中我们可以看到泛型的使用原则,它可以把实体中定义的属性对应字段存储起来,然后在U层中根据对应的字段在DataGridView控件中显示,这样既可以按需动态增加属性,也可以保证安全。
开始的时候对这部分很不理解,听到别人说泛型怎样觉得很高大上,其实路是一步步走过来的,只要踏实走好,问题自然迎刃而解。继续......