国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C# 利用反射動(dòng)態(tài)創(chuàng)建對象[摘錄]

2019-11-17 03:11:40
字體:
供稿:網(wǎng)友
C# 利用反射動(dòng)態(tài)創(chuàng)建對象[摘錄]

摘自:http://hi.baidu.com/yangyuhang/blog/item/f12ea90e13f214e336d12250.html

在VS.Net中,有很多種方法動(dòng)態(tài)調(diào)用對象的構(gòu)造函數(shù)。一是通過Activator類的CreateInstance()方法。這個(gè)方法我們在Remoting中也用過。它實(shí)際上是在本地或從遠(yuǎn)程創(chuàng)建對象類型,或獲取對現(xiàn)有遠(yuǎn)程對象的引用。它的方法簽名是:public static object CreateInstance(Type);(還有其他重載方法)注意它的返回值為object,MSDN對返回值的描述是:對新創(chuàng)建對象的引用。

二是通過Assembly類的方法CreateInstance()。方法名和前一樣,不過它不是靜態(tài)方法。Assembly是在System.Reflection命名空間中。方法簽名:public object CreateInstance(Type);(同樣還有其他重載方法)返回值仍然是object,MSDN對返回值的描述是:表示該類型的 Object 的實(shí)例,其區(qū)域性、參數(shù)、聯(lián)編程序和激活屬性設(shè)置為空引用(Visual Basic 中為 Nothing),并且 BindingFlags 設(shè)置為 Public 或 Instance,或者設(shè)置為空引用 (Nothing)(如果沒有找到 typeName)。

當(dāng)然還有其他方法,例如通過MethodInfo獲得方法信息后,根據(jù)IsConstructor屬性,判斷是否構(gòu)造函數(shù),再根據(jù)GetParamters()方法獲得參數(shù),最后通過Invoke()方法來調(diào)用,等等……。大家可以參考MSDN。

在這里,我且把問題簡單化,只調(diào)用其默認(rèn)構(gòu)造函數(shù)。通過CreateInstance()方法獲得object對象,再轉(zhuǎn)換為實(shí)際的自定義對象類型。事實(shí)證明,這種轉(zhuǎn)換為出現(xiàn)異常。根本的原因我還弄不清楚,初步的猜測,對于動(dòng)態(tài)加載的assembly,和手動(dòng)添加的assembly,F(xiàn)ramework將兩者視為了不同的assembly,即使我們使用的是同一個(gè)DLL。

我也注意到Actovator.CreateInstance()返回的是新創(chuàng)建對象的引用。是否是引用再作怪呢?但Assembly.CreateInstance()方法,根據(jù)MSDN的描述,返回的是object實(shí)例,然而仍然會(huì)拋出同樣的異常。所以,出現(xiàn)問題的具體原因,我確實(shí)無法解釋。

確實(shí)VS.Net博大精深,很多內(nèi)在的運(yùn)行機(jī)制我們不得而知。好吧,我們就知其然而不知其所以然吧,至少我現(xiàn)在已經(jīng)知道了利用反射動(dòng)態(tài)創(chuàng)建對象的解決之道!管它這么多,只要會(huì)用就行,退而求其次,也未嘗不可。

利用反射動(dòng)態(tài)創(chuàng)建對象,事實(shí)上就是通過Assembly動(dòng)態(tài)加載DLL。這里所謂的“對象”,應(yīng)分為兩種類型。不同的類型,解決的辦法也不相同。

一、.Net自身提供的類對象,例如Form對象、Control對象。

這也是我們在程序開發(fā)中會(huì)經(jīng)常用到的。一般我們開發(fā)應(yīng)用程序,都是將界面定義好。有多少個(gè)窗口,有多少個(gè)控件,事先做好,放在項(xiàng)目中。但有時(shí)作交互設(shè)計(jì)時(shí),還需要考慮用戶的請求。也許用戶希望某些窗體能夠自己決定加載的時(shí)間。也就是說,需要提供運(yùn)行時(shí)加載的功能。這時(shí),就需要通過反射來動(dòng)態(tài)創(chuàng)建對象了。(加載的窗體對象dll,通常是放在配置文件中。在.Net中,有專門的配置文件,它是xml格式。有關(guān)配置文件,我希望能專門寫一篇文章。在本文,我的例子是固定的加載程序集。) 1、創(chuàng)建要?jiǎng)討B(tài)加載的窗體對象

首先,創(chuàng)建一個(gè)窗體對象FirstForm,這個(gè)窗體只有一個(gè)控件Lable,來顯示窗體的名稱。然后我們將它編譯為dll文件FirstForm.dll,放在e:/AutoForm中。(要生成Dll文件,而不是exe,請?jiān)赟olution Explorer(解決方案資源管理器)中的 FirstForms 項(xiàng)目上單擊鼠標(biāo)右鍵,選擇 PRoperties(屬性)。在 Output Type(輸出類型)組合框中選擇 Class Library(類庫)。)

這個(gè)對象的程序集名為FirstForm.dll,類型為FirstForm.Form1。

2、創(chuàng)建應(yīng)用程序,動(dòng)態(tài)加載該對象

啟動(dòng)一個(gè)新的 Windows 窗體項(xiàng)目。將其命名為 AutoLoadForm。在新項(xiàng)目中包含的空窗體 Form1 中,將它的IsMdiContainer屬性更改為True。這樣,該窗體即變成一個(gè) MDI 父窗體。更改窗體的大小,使窗體的長和寬的尺寸大約為默認(rèn)值的兩倍。

將一個(gè)面板控件拖動(dòng)到窗體上,然后設(shè)置它的Dock屬性,使它靠接在窗體的頂部。更改面板的大小,使它的高度大約為 50px。

將一個(gè)組合框拖動(dòng)到面板上。將它命名為 cboForms,然后將它的DropDownStyle設(shè)置為DropDownList

最后,將一個(gè)按鈕拖動(dòng)到面板上。將它命名為 btnLoadForm,然后將它的Text屬性設(shè)置為LoadForm

此時(shí),F(xiàn)orm1 應(yīng)如圖 1 所示。

然后為程序添加命名空間: using System.Reflecton;

單擊btnLoadForm控件,寫入以下代碼:

private void btnLoadForm_Click(object sender, System.EventArgs e){ Assembly assembly = Assembly.LoadFrom(@"e:/AutoFormFirstForm.dll"); Type type = assembly.GetType("FirstForm.Form1");object obj = Activator.CreateInstance(type); Form formToShow = (Form)obj; formToShow.MdiParent = this; formToShow.Show(); }

代碼說明: 1)首先是通過Assembly.LoadFrom()來加載dll文件; 2)再通過GetType()來獲得要?jiǎng)?chuàng)建的Form類對象的類型。注意,在GetType()方法的參數(shù)為類型的名字,為string類型,同時(shí)該名字應(yīng)為類型的FullName,即:命名空間名.類名; 3)然后通過Activator.CreateInstance()方法創(chuàng)建該類型對象,返回object對象。 4)再將該對象強(qiáng)制轉(zhuǎn)換為Form類型。 5)最后調(diào)用即可。

運(yùn)行程序,單擊按鈕,結(jié)果如下:

結(jié)論:可以看到,對于.Net自身提供的類對象,我們對它直接強(qiáng)制轉(zhuǎn)換即可。不會(huì)出現(xiàn)任何問題。

二、自定義對象

前面已經(jīng)說過,對于自定義的對象,進(jìn)行強(qiáng)制轉(zhuǎn)換會(huì)拋出異常。因此,我們需要做些變通才行。

我們說,動(dòng)態(tài)加載的Dll和手工添加的dll引用,系統(tǒng)會(huì)認(rèn)為不是同一個(gè)Assembly。那么應(yīng)該怎么解決?想一想,對了,應(yīng)該使用接口。但是,這里使用接口的方法稍微有點(diǎn)特殊。還是先按步驟來講解吧。 1、創(chuàng)建一個(gè)接口,該接口包括要加載對象類的方法、屬性等:

新建一個(gè)“類庫”項(xiàng)目,取名為AutoObjectInterface:

using System;namespace AutoObjectInterface{public interface IAutoObject{void Print(string s); }}

這個(gè)接口很簡單,只是提供一個(gè)Print()方法而已。

然后將它編譯為Dll文件,名為AutoObjectInterface。

2、創(chuàng)建自定義類對象:

新建一個(gè)“類庫”項(xiàng)目,取名為AutoObject,添加前面創(chuàng)建的接口Dll引用:

using System;namespace AutoObject{public class TestObject:AutoObjectInterface.IAutoObject{public TestObject(){ }public void Print(string s){ Console.WriteLine(s); } }}

這個(gè)類實(shí)現(xiàn)了第一步創(chuàng)建的接口。注意,這里實(shí)現(xiàn)的接口不是直接寫在該類中,而是獨(dú)立的Dll。在這個(gè)類中,是添加了該接口的dll,然后再實(shí)現(xiàn)它。這就是前面說的使用接口的一點(diǎn)特殊性。為什么要這樣,是因?yàn)楹竺鎰?dòng)態(tài)加載時(shí),也要引用該接口Dll。我們動(dòng)態(tài)創(chuàng)建后的對象,正是轉(zhuǎn)換為該接口對象。由于實(shí)際的類和動(dòng)態(tài)創(chuàng)建的類都引用并實(shí)現(xiàn)了該接口Dll,因此它的轉(zhuǎn)換才能成功。這正是實(shí)現(xiàn)的關(guān)鍵!也許有人疑問:我們能否將接口就放在要?jiǎng)?chuàng)建的類中,然后實(shí)現(xiàn)它。編譯成dll文件,然后動(dòng)態(tài)加載該dll,同時(shí)也手動(dòng)添加該dll。動(dòng)態(tài)創(chuàng)建后的對象,再強(qiáng)制轉(zhuǎn)換為這個(gè)接口類型,不可以嗎?答案當(dāng)然是否定的,為什么?別問我,我也不知道!總之,我現(xiàn)在講的方法,才是通過反射動(dòng)態(tài)創(chuàng)建自定義對象的不二法門!!

也許會(huì)有人說我太武斷!如果你不信,去試試。如果用另外的方法能成功,我一定改正錯(cuò)誤。至少現(xiàn)在我能這樣武斷。

言歸正傳。現(xiàn)在我們再將給類編譯為dll。名為AutoObject.dll,放到e:/NewObject中。

3、利用反射動(dòng)態(tài)創(chuàng)建該對象:

新建一個(gè)控制臺(tái)項(xiàng)目,取名為StudyReflection,添加前面創(chuàng)建的接口Dll引用。代碼如下:AutoObjectInterface.IAutoObject

Obj = (AutoObjectInterface.IAutoObject)obj;

using System;using System.Reflection;namespace studyReflection{

上一篇:NPOI技術(shù),

下一篇:文件流

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 罗甸县| 酒泉市| 庆阳市| 枣强县| 开原市| 马龙县| 平度市| 手机| 上林县| 固镇县| 榆树市| 梁河县| 婺源县| 砀山县| 山阴县| 张家界市| 都匀市| 错那县| 华池县| 安泽县| 瑞金市| 祁东县| 舒兰市| 盱眙县| 新泰市| 武定县| 天镇县| 玉树县| 浦城县| 望都县| 长丰县| 富民县| 乐安县| 龙陵县| 平谷区| 芦山县| 建阳市| 轮台县| 兴国县| 资中县| 米泉市|