1. 程式人生 > >vb.net動態載入dll並執行dll中的某一個函式

vb.net動態載入dll並執行dll中的某一個函式

注意:下面的Dll檔案必須是用託管程式碼寫的,否則請使用API的相應函式進行動態載入。

一、

比如我事先寫了一個類,如下:

Public Class TestClass

    Public Function Add(ByVal add1 As IntegerByVal add2 As IntegerAs Integer

        Return add1 + add2

    End Function

End Class

然後編譯成了ClassDll.dll檔案.

二、

在另一個程式中,我寫入瞭如下程式碼

Public Function Add(ByVal add1 As Integer

ByVal add2 As IntegerAs Integer

        Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.LoadFile("ClassDll.dll")

        Dim classtemp As Type = asm.GetType("ClassDll.TestClass") '區分大小寫,wenjian ming bu neng xiangtong

        Dim obj As Object = asm.CreateInstance(classtemp.FullName)

        Dim me_Info As System.Reflection.MethodInfo = classtemp.GetMethod("Add")

        Dim paramter(1) As Object

        paramter(0) = add1

        paramter(1) = add2

        Return me_Info.Invoke(obj, paramter)

    End Function

執行上面的Add函式其功能和執行一中的Add函式是一樣的。

當然,執行上面的函式的另一種方法是:(之前我用上面的方法反射執行一個exe檔案裡的函式時,總是失敗,但是按照下面的方法就可以成功執行,你要是遇到問題時,不妨按照下面的方法試一試)

Public Function Add(ByVal add1 As IntegerByVal add2 As IntegerAs Integer

        Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.LoadFile("ClassDll.dll")

        Dim classtemp As Type = asm.GetType("ClassDll.TestClass")

        Dim obj As Object = asm.CreateInstance(classtemp.FullName)

        Return CallByName(obj, "Add", vbMethod,add1,add2)'這裡特別注意CallByName的用法

    End Function

1、上面的 System.Reflection.Assembly.LoadFile("ClassDll.dll")這一句裡的ClassDll.dll是我們編譯的那個dll檔案。如果其不是放在程式目錄下,這裡必須換成ClassDll.dll的絕對路徑。

2、Dim classtemp As Type = asm.GetType("ClassDll.TestClass")這裡的ClassDll.dll.TestClass類為什麼不是我們定義的那個TestClass類呢(ClassDll.dll是我們的dll名稱),你自己開啟那個dll檔案看一下就知道答案了。即我們用的時候類的前面必須加上我們的dll的名稱再加一個點,才構成我們的類。

3、paramter是我們函式要接收的引數。可以通過paramter來傳遞資料。

經測試,在wince下同樣適用

同樣,如何捕捉觸發事件

classtemp.GetType().AddEventHandler(obj, AddressOf obj_Timer)

...

Sub obj_Timer()
    ' Here to deal with the timer event of your object's instance.
End Sub

(IDutyDao)Assembly.Load(m_path).CreateInstance(className);
上述程式碼表示使用預設無引數的建構函式建立一個物件例項,如果要在建立物件例項的時候呼叫有引數的建構函式該如何實現呢?

考幫助文件使用過載的CreateInstance方法來建立物件例項的程式碼如下:

(IDutyDao)Assembly.Load(m_path).CreateInstance(className,false,BindingFlags.Public,null,
newobject[] { dataSource },null,null);

結果不行,報錯:

System.MissingMethodException: System.MissingMethodException: 未找到型別

“ToTop.CSIM.DAL.DaoSqlServerImpl.DutyDaoImpl”上的建構函式。

經過多次嘗試和網上搜索均未果,找到的都是一些提出遇到了同樣問題卻沒有解決辦法的帖子,最後靜下心來詳細檢視該過載方法的幫助文件,

發現第三個引數有文章,將程式碼調整如下:

(IDutyDao)Assembly.Load(m_path).CreateInstance(className,false,
BindingFlags.Public |BindingFlags.CreateInstance,null,newobject[] { dataSource },null,null);

結果還不行,報同樣的錯誤,於是只保留BindingFlags.CreateInstance繼續測試,將程式碼調整如下:

(IDutyDao)Assembly.Load(m_path).CreateInstance(className,false,BindingFlags.CreateInstance,
null,newobject[] { dataSource },null,null);

上述程式碼測試通過!

上述方法中的具體引數說明可參閱幫助文件。

在使用.NET建立的程式或元件時,元資料(metadata)和程式碼(code)都儲存於“自成一體”的單元中,這個單元稱為裝配件。我們可以在程式執行期間訪問這些資訊。
 
在System.Reflection中有這樣一個class————Assembly,我們可以通過它來載入一個裝配件。方法如下:
Assembly assm=Assembly.LoadFrom(fileName);
其中filename是要載入的裝配件的檔名稱(帶路徑)。
接下來,我們就可以通過使用System.Reflection內提供的Info classes來獲取裝配件中的資訊了。首先讓我們看一下這些Info classes:
MethodInfo 獲取某個“成員函式”的資訊,並提供對此“成員函式”元資料的訪問。
ParameterInfo 獲取某個“引數”的資訊,並提供對此“引數”元資料的訪問。
Constructorinfo 獲取某個“建構函式”的資訊,並提供對此“建構函式”元資料的訪問。
PropertyInfo 獲取某個“屬性”的資訊,並提供對此“屬性”元資料的訪問。
FieldInfo 獲取某個“資料成員”的資訊,並提供對此“資料成員”元資料的訪問。
EventInfo 獲取某個“事件”的資訊,並提供對此“事件”元資料的訪問。
上面列出的這些classes(除ParameterInfo外)的訪問操作,要通過一個Type物件來完成。比如我們要獲得一個裝配件的“成員函式”就要這樣做:
System.Reflection.Assembly ass=System.Reflection.Assembly.LoadFrom(fileName);
Type[] tp=ass.GetTypes();
System.Reflection.MethodInfo[] mi=tp[0].GetMethods();
使用同樣的方法我們還可以得到其它的資訊,如下:
獲得“建構函式”資訊:System.Reflection.ConstructorInfo[] ci=tp[0].GetConstructors();
獲得“屬性”資訊:System.Reflection.PropertyInfo[] pi=tp[0].GetProperties();
獲得“資料成員”資訊:System.Reflection.FieldInfo[] fi=tp[0].GetFields();
獲得“事件”資訊:System.Reflection.EventInfo[] ei=tp[0].GetEvents();
此外,我們可以通過ParameterInfo類來獲取“成員函式”和“建構函式”的引數資訊,如下:
獲取“成員函式”的引數資訊:System.Reflection.ParameterInfo[] pi=mi[0].GetParameters();
獲取“建構函式”的引數資訊:System.Reflection.ParameterInfo[] pi=ci[0].GetParameters();
ParameterInfo類有兩個重要的屬性:Name和ParameterType。通過它們我們可以得到“引數”的名稱和資料型別。
由於.NET將class的資訊以“元資料”的形式封裝在程式或是元件中,又提供了一系列可以獲取“元資料”的方法,所以我們可以程式執行期間來動態的訪問這些資訊。

以下摘自百度:http://zhidao.baidu.com/question/294391411.html
個人膚淺理解,反射實際上就是得到程式集中的屬性和方法.
實現步驟:
1,匯入using System.Reflection;
2,Assembly.Load("程式集")載入程式集,返回型別是一個Assembly
3,   foreach (Type type in assembly.GetTypes())
            {
                string t = type.Name;
            }
   得到程式集中所有類的名稱
4,Type type = assembly.GetType("程式集.類名");獲取當前類的型別
5,Activator.CreateInstance(type); 建立此型別例項
6,MethodInfo mInfo = type.GetMethod("方法名");獲取當前方法
7,mInfo.Invoke(null,方法引數);