【个人机房重构】—— 抽象工厂+反射+配置文件详解以及错误分析

背景:我们现在写的程序,用的数据库基本上都是SQLServer的。试想一下,如果我们以后还需要开发同样的程序,但是,所使用的数据库不同。那时,我们应该怎么做?是重新进行开发呢,还是在原有程序的基础上进行修改呢?


     在个人版的VB.NET的机房收费系统中,针对上边提到的问题,我们应该如何去解决。下边,Answer出场,Question退下。


一、Answer


    在这里,我们可以运用抽象工厂+反射+配置文件来解决上述问题。详情:《谈一谈:抽象工厂+反射+配置文件 实现数据库访问


二、New Question


问题解决了,但是,随着问题的解决,随之而出现的是新的问题。


先来看一段程序:


Imports System.Configuration    '配置文件命名空间
Imports System.Reflection       '反射命名空间
Imports IDAL                    '引用接口层

Public Class DataAccess
    '程序集名称(同时代表命名空间名称):DAL
    Private Shared ReadOnly AssemblyName As String = System.Configuration.ConfigurationManager.AppSettings("assname")
    '数据库类型:Sql
    Private Shared ReadOnly db As String = System.Configuration.ConfigurationManager.AppSettings("DB")
    '创建D层类SqlUserInfoDAL的实例
    Public Shared Function CreateUserInfo() As IDAL.IUserInfo
        Dim dalUserInfoName As String = AssemblyName & "." & db & "UserInfoDAL"        '要实例化的D层类的名称
        Return CType(Assembly.Load(AssemblyName).CreateInstance(dalUserInfoName), IUserInfo)
    End Function


    对于学过反射+配置文件+抽象工厂实现数据访问的人来说,这小段程序还是很容易理解的。我将这段程序用在了机房收费系统个人重构版中。如图所示:



但是在运行过程中却报了错:


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


    通过查资料,知道了一种解决方案:将DAL层的DAL.dll文件复制到UI层相应的目录下,如图所示。



    之后,程序正常运行,并通过CreateUserInfo()创建出了SqlUserInfoDAL的实例。


有了成功的经验,我便做了如下操作:

  • 在DAL层,添加了一个新的类:SqlWorkLogDAL
  • 在DataAccess中,添加了一个新的方法:CreateWorkLog()

    如下所示:



 '创建D层类SqlWorkLogDAL的实例
    Public Shared Function CreateWorkLog() As IDAL.IWorkLog
        Dim dalWorkLogName As String = AssemblyName & "." & db & "WorkLogDAL"          '要实例化的D层类的名称
        Return CType(Assembly.Load(AssemblyName).CreateInstance(dalWorkLogName), IWorkLog)
    End Function

但是运行后,还是报了错,不过这次错误不一样:


   “未将对象引用设置到对象的实例。”


    通过查资料,也找到了答案:修改DAL层--属性--编译--生成输出路径,将生成输出路径改到UI层\bin\Debug文件夹下

    虽然两种解决方法不一样,但是本质都是把DAL层的DAL.dll文件放到UI层


    那么,为什么第一种解决方法只有“短暂疗效”,而第二种方法可以“根治”呢?

    这时,我做了个尝试,我不去修改路径,而是再次把DAL层中的DAL.dll文件复制并替换我刚才复制到UI层的文件。

    结果成功了。

    这就说明了:两次复制的文件并非同一个文件,虽然它们都叫DAL.dll,但是在文件内部,它们一定发生了变化。

这里我们就要说说,dll文件是怎么生成的了。

    每个程序集下面都有两个文件夹bin和obj,如图:



     bin目录用来保存项目生成后程序集,obj目录用来保存编译结果。编译是分模块进行的,编译整个完成后会合并为一个.dll或.exe文件保存到bin目录下。而且采用增量编译的方式。

    所以,当我添加了一个新的类SqlWorkLogDAl后,生成的DAL.dll已经不是原来的DAL.dll了。

    复制的方式的缺陷在于:只要DAL层发生变化,就得通过手动复制来更新U层的DAL.dll文件。但是修改路径,就不用我们管了,它会自动将最新的DAL.dll文件生成到UI层。


那么为什么要把D层的.dll文件在U层生成呢?

     这就要知道Assembly.Load()是怎么定位程序集了?

     当你只给定程序集名称时,如“DAL”,那么CLR只会在应用程序的目录下查找,而咱们的应用程序在UI层,所以要在U层有DAL.dll。

    问题又来了:

    在U层,有Entity.dll,有BLL.dll,有DataAccess.dll……为什么就是没有DAL.dll,为什么只有它需要修改生成路径?

     这里就要看看程序的包图了:



    

    ---->代表依赖,也表示引用,那么从UI层看,UI层可以直接或间接地引用Facade层,BLL层,DataAccess层,IDAL层,但是没有引用DAL层,所以别的层的.dll文件会出现在U层,而DAL层的.dll文件没有出现在U层。

       


三、反思

   

    在使用抽象工厂+反射+配置文件时,我也遇到了上述的问题。当时为了解决问题,在网上查资料,咨询别人,最后也把问题给解决了。但是,在看到上边这篇关于如何解决问题的博客时,我陷入了深思。

    我记得米老师曾经给我说过:不会,可以去问别人;但是问别人问题的同时,也必须要知道人家为什么会知道这个问题的答案,人家是从哪知道的。

    我们在遇到问题的时候,都会去考虑怎么去解决问题,不管通过什么方法途径,基本上到最后,问题都能被解决。但是,有时候我们欠缺的是,深层次的思考。针对一个问题,可能解决了,就没事了,基本上不会去想:会不会有别的方法、途径,也能达到同样的效果?

    在遇到问题时,应该抓住问题,进行深层次的发掘,多角度的思考。

    学习,不仅要知其然,还要知其所以然。


 转自:徐晨阳:应用反射+配置文件+抽象工厂时出现的错误和原因分析


评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值