工廠模式的Assembly.Load(path).CreateInstance(className)出錯解決方法
1、問題描述
代碼展示
下麵是Factory中的一段代碼:
'********************************************** ' 文 件 名:DataAcess ' 命名空間:Factory ' 內 容: ' 功 能:創建用戶需要的接口 ' 文件關係: ' 作 者:令仔很忙 ' 小 組: ' 生成日期:2014-07-28 17:37:52 ' 版 本 號:V2.0 ' 修改日誌: ' 版權說明: '********************************************** Imports System.Reflection '引用 反射 命名空間 Imports System .Configuration Public Class DataAcess Private Shared ReadOnly assemblyName As String = "DAL" '數據程序集名稱 Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB") ''' <summary> ''' 創建用戶接口 ''' </summary> ''' <returns>返回IUser</returns> ''' <remarks></remarks> Public Function CreateIUser() As IDAL.IUser Dim className As String = assemblyName + "." + strDB + "UserDAL" '定義 命名空間.類 <pre name="code" ><span > </span>Return CType(Assembly.Load(assemblyName).CreateInstance(className), IDAL.IUser) ’容易出錯不易理解的地方
在這段代碼中,下麵這一語句是不易理解,容易出錯的地方
Return CType(Assembly.Load(assemblyName).CreateInstance(className), IDAL.IUser)
相關知識了解
下麵咱們先了解Assembly.Load(path).CreateInstance(className)
在VB.NET中,我們要使用反射,首先要搞清楚以下命名空間中幾個類的關係:
System.Reflection命名空間
(1) AppDomain:應用程序域,可以將其理解為一組程序集的邏輯容器
(2) Assembly:程序集類
(3) Module:模塊類
(4) Type:使用反射得到類型信息的最核心的類
他們之間是一種從屬關係,也就是說,一個AppDomain可以包含N個Assembly,一個Assembly可以包含N個Module,而一個Module可以包含N個Type.
在上麵的語句中我們用到的是Assembly這一類,在程序中,如果我們要動態加載一個程序集怎麼辦呢?有幾種方式可以使用,分別是Load,LoadFrom和LoadWithPartialName三個Assembly的靜態方法.我們主要說Load方法:
Assembly.Load("")的使用說明如下;
並不是命名空間。常用的是程序集名稱,也就是dll的名稱
重載列表
名稱說明
Assembly.Load(AssemblyName)在給定程序集的AssemblyName的情況下,加載程序集。
2、 出現的問題及解決方法
未能加載文件或程序集“DAL”或它的某一個依賴項,係統找不到指定文件
關於反射Assembly.Load("程序集").CreateInstance("命名空間.類"),而不管在哪一層寫這段代碼其中的("程序集")讀取的實際是web層bin文件夾下的dll,也就是說你反射的類的程序集dll在web層的bin下必須有。
注意CreateInstance()一定是命名空間.類名,否則創建的實例為空
Assembly.Load("程序集名")
出現這樣的錯誤有三種可能:
1)、DLL文件名與加載時的DLL文件名不一致。
2)、.DLL文件根本不存在,即出現丟失情況。
3)、加載DLL路徑錯誤,即DLL文件存在,但加載路徑不正確
看了下自己的問題,主要就是上麵的第三種情況,加載路徑不正確,怎麼解決?
找到文件夾DAL/bin/Debug,將裏麵與DAL相關的文件複製到UI/bin/Debug中去,運行,就可以了,後期的工作,如果每次遇到這中情況都手動添加的話會很麻煩,所以我們需要更改程序的生成路徑:
未將對象引用設置到對象的實例
上麵的語句中的CreateInstance(className),中className其實是需要反射的類型全名(包括命名空間的全路徑),如下圖:最終className返回的結果是DAL.SqlUserDAL
它是和DAL層相對應的,所以DAL層下的類的命名必須和它保持一致
其實這個問題有很多種情況,這隻是其中的一種出錯的地方和解決方法。
3、結束語
機房收費係統重構,剛開始開始敲三層或者開始敲七層,都是一段困難的過程,但是在這個過程中也是你進步最大的,不會了,多看看其他人的博客,多問,不理解可以先把別人的拿過來用,魯迅先生在《拿來主義》中說過一句話:“有選擇的拿,為我所用的拿,不卑不亢的拿”。借鑒是豁然開朗,是一種共鳴,為我所用,有更上一層樓的感覺;照抄是模仿,但走不出去,就會失去自我,如果說有臨界點的話,那就是我說我的話,用自己的話別人能聽懂而已。
最後更新:2017-04-03 05:39:34