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

首頁 > 學院 > 開發(fā)設計 > 正文

C#反射深入學習

2019-11-17 02:54:37
字體:
來源:轉載
供稿:網(wǎng)友
C#反射深入學習

C#反射

反射(Reflection)是.NET中的重要機制,通過放射,可以在運行時獲得.NET中每一個類型(包括類、結構、委托、接口和枚舉等)的成員,包括方法、屬性、事件,以及構造函數(shù)等。還可以獲得每個成員的名稱、限定符和參數(shù)等。有了反射,即可對每一個類型了如指掌。如果獲得了構造函數(shù)的信息,即可直接創(chuàng)建對象,即使這個對象的類型在編譯時還不知道。程序代碼在編譯后生成可執(zhí)行的應用,我們首先要了解這種可執(zhí)行應用程序的結構。應用程序結構分為應用程序域—程序集—模塊—類型—成員幾個層次,公共語言運行庫加載器管理應用程序域,這種管理包括將每個程序集加載到相應的應用程序域以及控制每個程序集中類型層次結構的內(nèi)存布局。程序集包含模塊,而模塊包含類型,類型又包含成員,反射則提供了封裝程序集、模塊和類型的對象。我們可以使用反射動態(tài)地創(chuàng)建類型的實例,將類型綁定到現(xiàn)有對象或從現(xiàn)有對象中獲取類型,然后調用類型的方法或訪問其字段和屬性。反射通常具有以下用途。(1)使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,以及從此程序集中查找類型并創(chuàng)建該類型的實例。(2)使用Module了解包含模塊的程序集以及模塊中的類等,還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。(3)使用ConstructorInfo了解構造函數(shù)的名稱、參數(shù)、訪問修飾符(如pulic 或PRivate)和實現(xiàn)詳細信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法來調用特定的構造函數(shù)。(4)使用MethodInfo了解方法的名稱、返回類型、參數(shù)、訪問修飾符(如pulic 或private)和實現(xiàn)詳細信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法來調用特定的方法。(5)使用FiedInfo了解字段的名稱、訪問修飾符(如public或private)和實現(xiàn)詳細信息(如static)等,并獲取或設置字段值。(6)使用EventInfo了解事件的名稱、事件處理程序數(shù)據(jù)類型、自定義屬性、聲明類型和反射類型等,添加或移除事件處理程序。(7)使用PropertyInfo了解屬性的名稱、數(shù)據(jù)類型、聲明類型、反射類型和只讀或可寫狀態(tài)等,獲取或設置屬性值。(8)使用ParameterInfo了解參數(shù)的名稱、數(shù)據(jù)類型、是輸入?yún)?shù)還是輸出參數(shù),以及參數(shù)在方法簽名中的位置等。System.Reflection.Emit命名空間的類提供了一種特殊形式的反射,可以在運行時構造類型。反射也可用于創(chuàng)建稱為類型瀏覽器的應用程序,使用戶能夠選擇類型,然后查看有關選定類型的信息。此外,Jscript等語言編譯器使用反射來構造符號表。System.Runtime.Serialization命名空間中的類使用反射來訪問數(shù)據(jù)并確定要永久保存的字段,System.Runtime.Remoting命名空間中的類通過序列化來間接地使用反射。

2008年03月01日 星期六 下午 07:36

[來源]http://blog.csdn.net/sscsgss/archive/2006/10/19/1341035.aspx 提綱: 1、 什么是反射 2、 命名空間與裝配件的關系 3、 運行期得到類型信息有什么用 4、 如何使用反射獲取類型 5、 如何根據(jù)類型來動態(tài)創(chuàng)建對象 6、 如何獲取方法以及動態(tài)調用方法 7、 動態(tài)創(chuàng)建委托 1、什么是反射 Reflection,中文翻譯為反射。 這是.Net中獲取運行時類型信息的方式,.Net的應用程序由幾個部分:‘程序集(Assembly)’、‘模塊(Module)’、‘類型 (class)’組成,而反射提供一種編程的方式,讓程序員可以在程序運行期獲得這幾個組成部分的相關信息,例如: Assembly類可以獲得正在運行的裝配件信息,也可以動態(tài)的加載裝配件,以及在裝配件中查找類型信息,并創(chuàng)建該類型的實例。 Type類可以獲得對象的類型信息,此信息包含對象的所有要素:方法、構造器、屬性等等,通過Type類可以得到這些要素的信息,并且調用之。 MethodInfo包含方法的信息,通過這個類可以得到方法的名稱、參數(shù)、返回值等,并且可以調用之。 諸如此類,還有FieldInfo、EventInfo等等,這些類都包含在System.Reflection命名空間下。 2、命名空間與裝配件的關系 很多人對這個概念可能還是很不清晰,對于合格的.Net程序員,有必要對這點進行澄清。 命名空間類似與java的包,但又不完全等同,因為Java的包必須按照目錄結構來放置,命名空間則不需要。 裝配件是.Net應用程序執(zhí)行的最小單位,編譯出來的.dll、.exe都是裝配件。 裝配件和命名空間的關系不是一一對應,也不互相包含,一個裝配件里面可以有多個命名空間,一個命名空間也可以在多個裝配件中存在,這樣說可能有點模糊,舉個例子: 裝配件A: namespace N1 { public class AC1 {…} public class AC2 {…} } namespace N2 { public class AC3 {…} public class AC4{…} } 裝配件B: namespace N1 { public class BC1 {…} public class BC2 {…} } namespace N2 { public class BC3 {…} public class BC4{…} } 這兩個裝配件中都有N1和N2兩個命名空間,而且各聲明了兩個類,這樣是完全可以的,然后我們在一個應用程序中引用裝配件A,那么在這個應用程序中,我們能看到N1下面的類為AC1和AC2,N2下面的類為AC3和AC4。 接著我們?nèi)サ魧的引用,加上對B的引用,那么我們在這個應用程序下能看到的N1下面的類變成了BC1和BC2,N2下面也一樣。 如果我們同時引用這兩個裝配件,那么N1下面我們就能看到四個類:AC1、AC2、BC1和BC2。 到這里,我們可以清楚一個概念了,命名空間只是說明一個類型是那個族的,比如有人是漢族、有人是回族;而裝配件表明一個類型住在哪里,比如有人住在北京、有人住在上海;那么北京有漢族人,也有回族人,上海有漢族人,也有回族人,這是不矛盾的。 上面我們說了,裝配件是一個類型居住的地方,那么在一個程序中要使用一個類,就必須告訴編譯器這個類住在哪兒,編譯器才能找到它,也就是說必須引用該裝配件。 那么如果在編寫程序的時候,也許不確定這個類在哪里,僅僅只是知道它的名稱,就不能使用了嗎?答案是可以,這就是反射了,就是在程序運行的時候提供該類型的地址,而去找到它。 有興趣的話,接著往下看吧。 3、運行期得到類型信息有什么用 有人也許疑問,既然在開發(fā)時就能夠寫好代碼,干嘛還放到運行期去做,不光繁瑣,而且效率也受影響。 這就是個見仁見智的問題了,就跟早綁定和晚綁定一樣,應用到不同的場合。有的人反對晚綁定,理由是損耗效率,但是很多人在享受虛函數(shù)帶來的好處的時侯還沒有意識到他已經(jīng)用上了晚綁定。這個問題說開去,不是三言兩語能講清楚的,所以就點到為止了。 我的看法是,晚綁定能夠帶來很多設計上的便利,合適的使用能夠大大提高程序的復用性和靈活性,但是任何東西都有兩面性,使用的時侯,需要再三衡量。 接著說,運行期得到類型信息到底有什么用呢? 還是舉個例子來說明,很多軟件開發(fā)者喜歡在自己的軟件中留下一些接口,其他人可以編寫一些插件來擴充軟件的功能,比如我有一個媒體播放器,我希望以后可以很方便的擴展識別的格式,那么我聲明一個接口: public interface IMediaFormat { string Extension {get;} Decoder GetDecoder(); } 這個接口中包含一個Extension屬性,這個屬性返回支持的擴展名,另一個方法返回一個解碼器的對象(這里我假設了一個Decoder的類,這個類提供把文件流解碼的功能,擴展插件可以派生之),通過解碼器對象我就可以解釋文件流。 那么我規(guī)定所有的解碼插件都必須派生一個解碼器,并且實現(xiàn)這個接口,在GetDecoder方法中返回解碼器對象,并且將其類型的名稱配置到我的配置文件里面。 這樣的話,我就不需要在開發(fā)播放器的時侯知道將來擴展的格式的類型,只需要從配置文件中獲取現(xiàn)在所有解碼器的類型名稱,而動態(tài)的創(chuàng)建媒體格式的對象,將其轉換為IMediaFormat接口來使用。 這就是一個反射的典型應用。 4、如何使用反射獲取類型 首先我們來看如何獲得類型信息。 獲得類型信息有兩種方法,一種是得到實例對象 這個時侯我僅僅是得到這個實例對象,得到的方式也許是一個object的引用,也許是一個接口的引用,但是我并不知道它的確切類型,我需要了解,那么就可以通過調用System.Object上聲明的方法GetType來獲取實例對象的類型對象,比如在某個方法內(nèi),我需要判斷傳遞進來的參數(shù)是否實現(xiàn)了某個接口,如果實現(xiàn)了,則調用該接口的一個方法: … public void Process( object processObj ) { Type t = processsObj.GetType(); if( t.GetInterface(“ITest”) !=null ) … } … 另外一種獲取類型的方法是通過Type.GetType以及Assembly.GetType方法,如: Type t = Type.GetType(“System.String”); 需要注意的是,前面我們講到了命名空間和裝配件的關系,要查找一個類,必須指定它所在的裝配件,或者在已經(jīng)獲得的Assembly實例上面調用GetType。 本裝配件中類型可以只寫類型名稱,另一個例外是mscorlib.dll,這個裝配件中聲明的類型也可以省略裝配件名稱(.Net裝配件編譯的時候,默認都引用了mscorlib.dll,除非在編譯的時候明確指定不引用它),比如: System.String是在mscorlib.dll中聲明的,上面的Type t = Type.GetType(“System.String”)是正確的 System.Data.DataTable是在System.Data.dll中聲明的,那么: Type.GetType(“System.Data.DataTable”)就只能得到空引用。 必須:Type t = Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 這樣才可以,大家可以看下面這個帖子: http://expert.csdn.net/Expert/topic/2210/2210762.xml?temp=.1919977 QQchen的回答很精彩 5、如何根據(jù)類型來動態(tài)創(chuàng)建對象 System.Activator提供了方法來根據(jù)類型動態(tài)創(chuàng)建對象,比如創(chuàng)建一個DataTable: Type t = Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); DataTable table = (DataTable)Activator.CreateInstance(t); 例二:根據(jù)有參數(shù)的構造器創(chuàng)建對象 namespace TestSpace { public class TestClass { private string _value; public TestClass(string value) { _value=value; } } } … Type t = Type.GetType(“TestSpace.TestClass”); Object[] constructParms = new object[] {“hello”}; //構造器參數(shù) TestClass obj = (TestClass)Activator.CreateInstance(t,constructParms); … 把參數(shù)按照順序放入一個Object數(shù)組中即可 6、如何獲取方法以及動態(tài)調用方法 namespace TestSpace { public class TestClass { private string _value; public TestClass() { } public TestClass(string value) { _value = value; } public string GetValue( string prefix ) { if( _value==null ) return "NULL"; else return prefix+" : "+_value; } public string Value { set { _value=value; } get { if( _value==null ) return "NULL"; else return _value; } } } } 上面是一個簡單的類,包含一個有參數(shù)的構造器,一個GetValue的方法,一個Value屬性,我們可以通過方法的名稱來得到方法并且調用之,如: //獲取類型信息 Type t = Type.GetType("TestSpace.TestClass"); //構造器的參數(shù) object[] constuctParms = new object[]{"timmy"}; //根據(jù)類型創(chuàng)建對象 object dObj = Activator.CreateInstance(t,constuctParms); //獲取方法的信息 MethodInfo method = t.GetMethod("GetValue"); //調用方法的一些標志位,這里的含義是Public并且是實例方法,這也是默認的值 BindingFlags flag = BindingFlags.Public | BindingFlags.Instance; //GetValue方法的參數(shù) object[] parameters = new object[]{"Hello"}; //調用方法,用一個object接收返回值 object returnValue = method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null); 屬性與方法的調用大同小異,大家也可以參考MSDN 7、動態(tài)創(chuàng)建委托 委托是C#中實現(xiàn)事件的基礎,有時候不可避免的要動態(tài)的創(chuàng)建委托,實際上委托也是一種類型:System.Delegate,所有的委托都是從這個類派生的 System.Delegate提供了一些靜態(tài)方法來動態(tài)創(chuàng)建一個委托,比如一個委托: namespace TestSpace { delegate string TestDelegate(string value); public class TestClass { public TestClass() { } public void GetValue(string value) { return value; } } } 使用示例: TestClass obj = new TestClass(); //獲取類型,實際上這里也可以直接用typeof來獲取類型 Type t = Type.GetType(“TestSpace.TestClass”); //創(chuàng)建代理,傳入類型、創(chuàng)建代理的對象以及方法名稱 TestDelegate method = (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”); String returnValue = method(“hello”); 到這里,我們簡單的講述了反射的作用以及一些基本的用法,還有很多方面沒有涉及到,有興趣的朋友可以參考MSDN。 很奇怪,很多人都不愿看MSDN,其實你想要的答案,99%都可以在里面找到。

c#中的反射

c#中的反射 作者:YAOTIEBING反射的概述反射的定義:審查元數(shù)據(jù)并收集關于它的類型信息的能力。元數(shù)據(jù)(編譯以后的最基本數(shù)據(jù)單元)就是一大堆的表,當編譯程序集或者模塊時,編譯器會創(chuàng)建一個類定義表,一個字段定義表,和一個方法定義表等,。System.reflection命名空間包含的幾個類,允許你反射(解析)這些元數(shù)據(jù)表的代碼和反射相關的命名空間(我們就是通過這幾個命名空間訪問反射信息):System.Reflection.MemberInfo System.Reflection.EventInfo System.Reflection.FieldInfo Sy

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 西藏| 呼图壁县| 巫溪县| 万州区| 尼玛县| 遵义县| 米林县| 开封市| 广河县| 丽江市| 河曲县| 崇义县| 城市| 睢宁县| 安溪县| 南投市| 岑溪市| 凤阳县| 合阳县| 维西| 贺州市| 康保县| 定远县| 巨野县| 若尔盖县| 耿马| 屏东市| 钟山县| 平舆县| 灵璧县| 铜陵市| 永嘉县| 汾阳市| 正宁县| 遂宁市| 河津市| 阿克| 平安县| 望谟县| 裕民县| 巨鹿县|