【.NET机房重构】——泛型集合

来源:互联网 发布:网络打印机如何设置ip 编辑:程序博客网 时间:2024/05/19 04:03


    对于刚刚接触VB.NET的我来说,VB.NET这门语言除了知道它是面向对象的,与VB有很多地方都是类似的之外,其他的就真的没什么了。所以重构过程中会遇到很多问题,有些问题会让你绞尽脑汁,花上一周的时间也不一定能够解决。这个问题就真的花了一周还要多的时间来解决,仅以这篇博客来记录解决问题的过程。


一、遇到的问题


    记得敲第一版机房收费系统的时候,一个主要的问题就是将数据库表中的信息显示到窗体控件中,当时这个问题困扰了自己很久,查了很多资料。到重构时遇到了同样的问题,不过好在.NET中利用泛型集合添加数据,过程会简单很多。


二、解决过程

    方法一:

    刚开始遇到这个问题的时候,由于纯三层敲得是传实体的,所以原本想着可以直接让DataGridView控件的DataSource等于实体,可是由于传实体从D层传回来的只是一条记录,所以在控件中显示的也只有一条数据。所以传实体这种方法被pass掉了,就开始想别的办法。下面是传实体时U层的代码:

<span style="font-family:KaiTi_GB2312;font-size:18px;">''' <summary>    ''' 将从D层传回来的数据显示在DataGridView控件中    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged        Dim User As New Entity.UserInfo        Dim eUser As Entity.UserInfo        Dim aBLL As New BLL.AddOrDelUserBLL        User.Level = ComboBox1.Text        eUser = aBLL.SelectUser(User)        DataGridView1.DataSource = eUser    End Sub</span>


    这种结果就是在控件中只显示一行记录,正是由于这样,才想到了怎么添加多行,于是也就有了下面DataTable的方法。

    方法二:

    曾经师傅开会时提过一句,不要返回DataTable。因为当时还没敲到需要用的地方,所以也没放在心上。不过,现在看来,返回DataTable也不乏是一种好方法。如果将DataGridView控件的DataSource设置为DataTable,这样表中的所有信息就都能被控件显示出来了。因为DataTable是DataSet中的数据表,它能代表的就是D层从数据库中调出来的数据表,只要D层查询的是多条记录,那么在DataTable中的也就是多条记录,DataGridView控件显示的自然也就是多条记录。后来,经实践,发现这种方法确实可行,不过师傅说不能返回DataTable,自然也是有它的道理的。因为返回DataTable会破坏三层结构,具体内容请看周洲童鞋的博客:三层架构中DataTable华丽变身泛型集合。返回DataTable的代码类似,也就是将D层查询的数据赋给DataTable,返回给B层,然后再返回到U层,最后用控件显示。


三、泛型


    虽然返回DataTable非常方便,理解起来也很容易,由于DataTable对数据保护性不强,所以只能忍痛割爱了。张晗要验收设计模式的时候,就跟着他一起去听了听,他师父给他提了几个名词,让他回来查一下,其中有一个就是泛型。于是就百度了一下,泛型是程序设计语言的一种特性,允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些可变部分在使用前必须做出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入类型参数这个概念。我理解的泛型,就是不定义参数类型,等到使用的时候再指明,就像接口一样,只提供方法名,等类去具体实现的时候再实例化。


    泛型类是引用类型,所谓的引用类型就是由类型的实际值的引用来表示的数据类型,相对的就是值类型。引用类似于指针,它并不表示实际值,引用类型和值类型的关系就像遛狗时牵狗的绳子和狗的关系。泛型类的类型参数在实际类型运行时不会被消除,而且泛型类属于堆对象,所以在运行时不需要来回进行类型转换,所以运行起来的速度要快一些。


四、泛型集合


    泛型常用的用途就是泛型集合,命名空间System.Collection.Generic中包含了很多基于泛型的集合类,使用泛型集合类可以提高安全性,也可以避免非泛型集合类重复的装箱和拆箱,也就是值类型和引用类型的转换。泛型集合类有很多,List<T>、Dictionary<T>等都可以实现类似功能。


    List<T>类中,List是泛型集合或者类的名称,T是类型参数,List<T>类提供对列表的搜索、排序、操作的方法。List<T>类中有很多方法,比如:

        添加一个元素:List.Add(T Item)

        删除一个元素:List.Remove(T Item)

        集合的清空:List.Clear()

     其实刚开始研究泛型集合的时候,由于对它太不了解了,所以并不知道List.Add()方法添加的只是一行,所以第一次的U层代码并不是那么写的,而是

<span style="font-family:KaiTi_GB2312;font-size:18px;">List.Add(eUser)DataGridView1.DataSource=List</span>
显然这样写的结果就只能显示一行数据了

    以List<T>为例,看一下利用泛型集合是怎么将数据显示在DataGridView控件中的。


    添加和删除用户窗体中,当点击ComboBox时,DataGridView控件应该显示对应权限的用户信息,所以在D层应该先查询出所要显示的字段,然后赋给泛型集合,我这里是返回的DataTable,然后再转换成泛型集合的。


D层代码:

<span style="font-family:KaiTi_GB2312;font-size:18px;">''' <summary>    ''' 查询用户表中的数据,并传给泛型集合    ''' </summary>    ''' <param name="User"></param>    ''' <returns>泛型集合</returns>    ''' <remarks></remarks>    Public Function SelectUser(ByVal User As Entity.UserInfo) As List(Of Entity.UserInfo)        Dim sql As String = "Select ID,UserName,Head From T_UserInfo where Level = '" & User.Level & "'"        Dim cmd As SqlCommand = New SqlCommand(sql, conn)        Dim reader As SqlDataReader        Dim UserList As New List(Of Entity.UserInfo)        Dim dt As New DataTable        conn.Open()        reader = cmd.ExecuteReader        dt.Load(reader, Data.LoadOption.Upsert)        If (dt.Rows.Count > 0) Then            UserList = Helper.ConverToList(dt, UserList)            Return UserList        Else            Throw New Exception("没有记录!")            Return Nothing        End If        conn.Close()    End Function</span>
具体的转换类的代码在周洲博客里面有,而且也有解释。


    B层其实就是将U层和D层连接起来,起到通讯的作用,由于没有什么复杂的逻辑判断,代码比较简单,这里就不贴出来了。


    至于U层,就是将传回来的集合里的内容显示出来,代码如下:

<span style="font-family:KaiTi_GB2312;font-size:18px;">''' <summary>    ''' 将从D层传回来的数据显示在DataGridView控件中    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged        Dim User As New Entity.UserInfo        Dim aBLL As New BLL.AddOrDelUserBLL        Dim List As New List(Of Entity.UserInfo)        Dim i As Integer        User.Level = ComboBox1.Text        List = aBLL.SelectUser(User)        For i = 0 To List.Count            DataGridView1.DataSource = List        Next    End Sub</span>
    这样,实现了用泛型集合向DataGridView控件中添加数据了。


总结

    有时候,我们不能只是图个便利。就拿上面这个例子来说,虽然返回DataTable很方便,但是会破坏三层结构,而且DataTable的信息跟数据库中的信息是关联的,容易造成数据库信息被修改。而相反的,繁琐一点的程序可能更安全。还有就是,遇到问题一定要有自己的一个思考过程,即使你的方法可能完全不合逻辑,但是也是一次尝试。就像上面所说,不利用任何集合只是一个实体就想让控件显示多条记录,真不知道自己当时怎么想的。这也就是学习的过程吧,其实本没有什么对与错,只是适合不适合,结果对了,说明你的方法适合解决这个问题,关键还是要看试的过程。


0 0
原创粉丝点击