【.NET机房重构】——再看抽象工厂加反射实现登录

    纯三层的机房重构终于敲完了,但是还需要加设计模式,这又是一道难题。研究了半天的时间,终于对七层的运行步骤熟悉了一些,也对抽象工厂加反射和配置文件了解的更多了一些,下面就看看我的新认识。


技术分享

    这是七层的包图,说是七层,但是七层并不是严格意义上的七层,只不过在三层的基础上加上了工厂、外观和接口,用到设计模式的地方多了自然就形成了一层,所以就有了现在的七层。


各层代码

界面层

    分层之后界面层的功能很简单,不能再有逻辑判断,可以有些简单的是否为空或者是否为数字等。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class frmLogin
    ''' <summary>
    ''' 登录
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
        Dim lFac As New Facade.loginFac
        Dim result As String
        Dim User As New Entity.UserInfo
        User.ID = txtID.Text.Trim
        User.Password = txtPwd.Text.Trim
        result = lFac.Confirm(User)
        Select Case result
            Case "该用户不存在!"
                txtID.Focus()
                txtID.SelectAll()
            Case "密码错误!"
                txtPwd.Focus()
                txtPwd.SelectAll()
            Case "登录成功!"
                MsgBox("登录成功!")
        End Select
    End Sub

End Class</span>


外观层

    我理解的外观层其实放的是U层需要用到的方法,这样U层就只跟外观层打交道就好了,它不需要知道具体实现,这样就很好的做到了解耦。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class loginFac
    ''' <summary>
    ''' 验证用户
    ''' </summary>
    ''' <param name="User"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Confirm(ByVal User As Entity.UserInfo) As String
        Dim ConfirmUser As New BLL.LoginBLL
        If Not ConfirmUser.IsExist(User) Then
            Return "该用户不存在!"
        Else
            If Not ConfirmUser.ConfirmPwd(User) Then
                Return "密码错误!"
            Else
                Return "登录成功!"
            End If
        End If
    End Function
End Class</span>


逻辑判断层

    逻辑判断层顾名思义,就是进行逻辑判断的,登录时的判断用户是否存在和密码输入是否正确就在B层进行判断。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class LoginBLL
    ''' <summary>
    ''' 验证用户是否存在
    ''' </summary>
    ''' <param name="User"></param>
    ''' <returns>布尔值</returns>
    ''' <remarks></remarks>
    Public Function IsExist(ByVal User As Entity.UserInfo) As Boolean
        Dim IUser As IDAL.IUserInfo
        Dim factory As New Factory.DataAccess

        IUser = factory.CreateUserInfo()
        If IUser.SelectUser(User)(0).ID = "" Then
            Return False
        Else
            Return True
        End If
    End Function
    ''' <summary>
    ''' 验证密码是否正确
    ''' </summary>
    ''' <param name="User"></param>
    ''' <returns>布尔值</returns>
    ''' <remarks></remarks>
    Public Function ConfirmPwd(ByVal User As Entity.UserInfo) As Boolean
        Dim IUser As IDAL.IUserInfo
        Dim factory As New Factory.DataAccess

        IUser = factory.CreateUserInfo()
        If IUser.SelectUser(User)(0).Password = "" Then
            Return False
        Else
            Return True
        End If
    End Function
End Class</span>


接口

    接口是定义一个方法名,为了让D层去实现,我觉得接口的存在也很好的做到了解耦,在B层就只需要声明一个接口,具体实现也不需要了解。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Interface IUserInfo
    Function SelectUser(ByVal User As Entity.UserInfo) As List(Of Entity.UserInfo)
End Interface</span>


工厂

    工厂的功能就是批量的产生类,就像现实中的工厂,给了订单之后,就可以批量生产。其实接口和工厂就像现实生活中的老板和工厂,老板是联系顾客和工厂的中介,接口也同样。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class DataAccess
    Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB")
    ''' <summary>
    ''' 产生类
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CreateUserInfo() As IDAL.IUserInfo
        Return CType(Assembly.Load("DAL").CreateInstance("DAL.LoginDAL"), IDAL.IUserInfo)
    End Function
End Class</span>


数据层

    D层主要是和数据库打交道,将你想要的信息查询出来并返回,或者按照你的意愿更新数据库的信息,也就是数据库的增删改查。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class LoginDAL : Implements IDAL.IUserInfo
    ''' <summary>
    ''' 查询Users表的信息
    ''' </summary>
    ''' <param name="User"></param>
    ''' <returns>泛型集合</returns>
    ''' <remarks></remarks>
    Public Function SelectUser(ByVal User As Entity.UserInfo) As List(Of Entity.UserInfo) Implements IDAL.IUserInfo.SelectUser
        Dim helper As New SQLHelper
        Dim sql As String = "Select * From Users Where ID = '" & User.ID & "'"
        Dim dt As New DataTable
        Dim lUser As New List(Of Entity.UserInfo)
        dt = helper.ExecuteSelect(sql, CommandType.Text)
        lUser = ConvertHelper.ConverToList(dt, lUser)
        Return lUser
    End Function
End Class</span>

利用反射换数据库

       Assembly.Load("程序集名称").CreateInstance("命名空间.类名称")

    程序集名称就是类库属性中的程序集名称,命名空间就是类库属性中的根命名空间,类名称就是该命名空间下的类名。利用反射换数据库的实质其实就是,如果要使用不同的数据库,D层就应该有不同的类,比如用Sql Server时类名为LoginDALSql,用Oracle时类名应该为LoginDALOra。因为数据库类型可以用配置文件中的字符串来变动,所以在配置文件中需这样写:

<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="strConn" value="Server=localhost;DataBase=Login;User=sa;Password=0722"/>
    <add key="DB" value="Sql"/>
  </appSettings>
</configuration></span>


然后工厂中的代码为

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class DataAccess
    Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB")
    ''' <summary>
    ''' 利用反射
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CreateUserInfo() As IDAL.IUserInfo
        Return CType(Assembly.Load("DAL").CreateInstance("DAL.LoginDAL" & strDB), IDAL.IUserInfo)
    End Function
End Class</span>

    “DB”是读取的配置文件中的字符串,strDB是定义的换数据库的字符串,这样工厂返回的类名应该是“DAL.LoginDALSql”。如果要换数据库,只需要将配置文件的“Sql”换成“Ora”就行了,工厂返回的类名就是“DAL.LoginDALOra”,这样就可以实现不同数据库操作类的更换。


遇到的错误

登录中主要遇到了两个问题:

1、未能加载文件或程序集“DAL”或它的某一个依赖项。系统找不到指定文件

    这个错误参照李社河师哥的一篇博客解决的:解决方法参考

2、配置系统未能初始化

    这个问题网上有很多解决方法,其实最主要的原因就是配置文件写错了,可能是顺序错误或者什么的。我出现的错误是大小写的问题,应该写成大写的写成了小写,就这样就酿成了悲剧。


总结

    对于自己学的东西,不管是什么东西,都要先着手去做,开始的时候不知道该怎么做,可能改了又改,可是就是这个过程才能让自己对它理解更深。另外,学什么东西不要只看到表面,不理解深层,这样容易卡在一个小问题上。





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。