• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級(jí)} {C#界面,C++核心算法} {設(shè)計(jì)模式} {C#基礎(chǔ)}

            c#的反射

             反射的概述 
               
              反射appDomain 的程序集 
               
              反射單個(gè)程序集 
               
              利用反射獲取類型信息 
               
              設(shè)置反射類型的成員 
               
              通過(guò)反射創(chuàng)建類型的實(shí)例 
               
              反射類型的接口 
               
              反射的性能 
               
              反射的概述 
               
              反射的定義:審查元數(shù)據(jù)并收集關(guān)于它的類型信息的能力。元數(shù)據(jù)(編譯以后的最基本數(shù)據(jù)單元)就是一大堆的表,當(dāng)編譯程序集或者模塊時(shí),編譯器會(huì)創(chuàng)建一個(gè)類定義表,一個(gè)字段定義表,和一個(gè)方法定義表等,。System.reflection命名空間包含的幾個(gè)類,允許你反射(解析)這些元數(shù)據(jù)表的代碼 
               
              和反射相關(guān)的命名空間(我們就是通過(guò)這幾個(gè)命名空間訪問(wèn)反射信息): 
               
              System.Reflection.MemberInfo 
               
               System.Reflection.EventInfo 
               
               System.Reflection.FieldInfo 
               
               System.Reflection.MethodBase 
               
               System.Reflection.ConstructorInfo 
               
               System.Reflection.MethodInfo 
               
               System.Reflection.PropertyInfo 
               
               System.Type 
               
               System.Reflection.Assembly 
               
              反射的層次模型: 
               
               
              注:層次間都是一對(duì)多的關(guān)系 
               
              反射的作用: 
               
              1. 可以使用反射動(dòng)態(tài)地創(chuàng)建類型的實(shí)例,將類型綁定到現(xiàn)有對(duì)象,或從現(xiàn) 有對(duì)象中獲取類型 
               
              2. 應(yīng)用程序需要在運(yùn)行時(shí)從某個(gè)特定的程序集中載入一個(gè)特定的類型,以便實(shí)現(xiàn)某個(gè)任務(wù)時(shí)可以用到反射。 
               
              3. 反射主要應(yīng)用與類庫(kù),這些類庫(kù)需要知道一個(gè)類型的定義,以便提供更多的功能。 
               
              應(yīng)用要點(diǎn): 
               
              1. 現(xiàn)實(shí)應(yīng)用程序中很少有應(yīng)用程序需要使用反射類型 
               
              2. 使用反射動(dòng)態(tài)綁定需要犧牲性能 
               
              3. 有些元數(shù)據(jù)信息是不能通過(guò)反射獲取的 
               
              4. 某些反射類型是專門為那些clr 開(kāi)發(fā)編譯器的開(kāi)發(fā)使用的,所以你要意識(shí)到不是所有的反射類型都是適合每個(gè)人的。 
               
               
               
              反射appDomain 的程序集 
               
               當(dāng)你需要反射AppDomain 中包含的所有程序集,示例如下: 
               static void Main 
               
               { 
               
               //通過(guò)GetAssemblies 調(diào)用appDomain的所有程序集 
               
              foreach (Assembly assem in Appdomain.currentDomain.GetAssemblies()) 
               
              { 
               
               //反射當(dāng)前程序集的信息 
               
               reflector.ReflectOnAssembly(assem) 
               
              } 
               
              } 
               
              說(shuō)明:調(diào)用AppDomain 對(duì)象的GetAssemblies 方法 將返回一個(gè)由System.Reflection.Assembly元素組成的數(shù)組。 
               
              反射單個(gè)程序集 
               
              上面的方法講的是反射AppDomain的所有程序集,我們可以顯示的調(diào)用其中的一個(gè)程序集,system.reflecton.assembly 類型提供了下面三種方法: 
               
              1. Load 方法:極力推薦的一種方法,Load 方法帶有一個(gè)程序集標(biāo)志并載入它,Load 將引起CLR把策略應(yīng)用到程序集上,先后在全局程序集緩沖區(qū),應(yīng)用程序基目錄和私有路徑下面查找該程序集,如果找不到該程序集系統(tǒng)拋出異常 
               
              2. LoadFrom 方法:傳遞一個(gè)程序集文件的路徑名(包括擴(kuò)展名),CLR會(huì)載入您指定的這個(gè)程序集,傳遞的這個(gè)參數(shù)不能包含任何關(guān)于版本號(hào)的信息,區(qū)域性,和公鑰信息,如果在指定路徑找不到程序集拋出異常。 
               
              3. LoadWithPartialName:永遠(yuǎn)不要使用這個(gè)方法,因?yàn)閼?yīng)用程序不能確定再在載入的程序集的版本。該方法的唯一用途是幫助那些在.Net框架的測(cè)試環(huán)節(jié)使用.net 框架提供的某種行為的客戶,這個(gè)方法將最終被拋棄不用。 
               
              注意:system.AppDomain 也提供了一種Load 方法,他和Assembly的靜態(tài)Load 方法不一樣,AppDomain的load 方法是一種實(shí)例方法,返回的是一個(gè)對(duì)程序集的引用,Assembly的靜態(tài)Load 方發(fā)將程序集按值封裝發(fā)回給發(fā)出調(diào)用的AppDomain.盡量避免使用AppDomain的load 方法 
               
               
               
              利用反射獲取類型信息 
               
              前面講完了關(guān)于程序集的反射,下面在講一下反射層次模型中的第三個(gè)層次,類型反射 
               
              一個(gè)簡(jiǎn)單的利用反射獲取類型信息的例子: 
               
              using system; 
               
              using sytem.reflection; 
               
              class reflecting 
               
              { 
               
               static void Main(string[]args) 
               
              { 
               
               reflecting reflect=new reflecting();//定義一個(gè)新的自身類 
               
               //調(diào)用一個(gè)reflecting.exe程序集 
               
               assembly myAssembly =assembly.loadfrom(“reflecting.exe”) 
               
               reflect.getreflectioninfo(myAssembly);//獲取反射信息 
               
              } 
               
              //定義一個(gè)獲取反射內(nèi)容的方法 
               
              void getreflectioninfo(assembly myassembly) 
               
              { 
               
               type[] typearr=myassemby.Gettypes();//獲取類型 
               
               foreach (type type in typearr)//針對(duì)每個(gè)類型獲取詳細(xì)信息 
               
               { 
               
               //獲取類型的結(jié)構(gòu)信息 
               
               constructorinfo[] myconstructors=type.GetConstructors; 
               
               //獲取類型的字段信息 
               
               fieldinfo[] myfields=type.GetFiedls() 
               
               //獲取方法信息 
               
               MethodInfo myMethodInfo=type.GetMethods(); 
               
               //獲取屬性信息 
               
               propertyInfo[] myproperties=type.GetProperties 
               
               //獲取事件信息 
               
               EventInfo[] Myevents=type.GetEvents; 
               
               
               
              } 
               
              } 
               
              } 
               
              其它幾種獲取type對(duì)象的方法: 
               
              1. System.type 參數(shù)為字符串類型,該字符串必須指定類型的完整名稱(包括其命名空間) 
               
              2. System.type 提供了兩個(gè)實(shí)例方法:GetNestedType,GetNestedTypes 
               
              3. Syetem.Reflection.Assembly 類型提供的實(shí)例方法是:GetType,GetTypes,GetExporedTypes 
               
              4. System.Reflection.Moudle 提供了這些實(shí)例方法:GetType,GetTypes,FindTypes 
               
              設(shè)置反射類型的成員 
               
               反射類型的成員就是反射層次模型中最下面的一層數(shù)據(jù)。我們可以通過(guò)type對(duì)象的GetMembers 方法取得一個(gè)類型的成員。如果我們使用的是不帶參數(shù)的GetMembers,它只返回該類型的公共定義的靜態(tài)變量和實(shí)例成員,我們也可以通過(guò)使用帶參數(shù)的GetMembers通過(guò)參數(shù)設(shè)置來(lái)返回指定的類型成員。具體參數(shù)參考msdn 中system.reflection.bindingflags 枚舉類型的詳細(xì)說(shuō)明。 
               
              例如: 
               
               
               
              //設(shè)置需要返回的類型的成員內(nèi)容 
               
              bindingFlags bf=bingdingFlags.DeclaredOnly|bingdingFlags.Nonpublic|BingdingFlags.Public; 
               
              foreach (MemberInfo mi int t.getmembers(bf)) 
               
              { 
               
               writeline(mi.membertype) //輸出指定的類型成員 
               
              } 
               
              通過(guò)反射創(chuàng)建類型的實(shí)例 
               
              通過(guò)反射可以獲取程序集的類型,我們就可以根據(jù)獲得的程序集類型來(lái)創(chuàng)建該類型新的實(shí)例,這也是前面提到的在運(yùn)行時(shí)創(chuàng)建對(duì)象實(shí)現(xiàn)晚綁定的功能 
               
              我們可以通過(guò)下面的幾個(gè)方法實(shí)現(xiàn): 
               
              1. System.Activator 的CreateInstance方法。該方法返回新對(duì)象的引用。具體使用方法參見(jiàn)msnd 
               
              2. System.Activator 的createInstanceFrom 與上一個(gè)方法類似,不過(guò)需要指定類型及其程序集 
               
              3. System.Appdomain 的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap 
               
              4. System.type的InvokeMember實(shí)例方法:這個(gè)方法返回一個(gè)與傳入?yún)?shù)相符的構(gòu)造函數(shù),并構(gòu)造該類型。 
               
              5. System.reflection.constructinfo 的Invoke實(shí)例方法 
               
              反射類型的接口 
               
              如果你想要獲得一個(gè)類型繼承的所有接口集合,可以調(diào)用Type的FindInterfaces GetInterface或者GetInterfaces。所有這些方法只能返回該類型直接繼承的接口,他們不會(huì)返回從一個(gè)接口繼承下來(lái)的接口。要想返回接口的基礎(chǔ)接口必須再次調(diào)用上述方法。 
               
              反射的性能: 
               
              使用反射來(lái)調(diào)用類型或者觸發(fā)方法,或者訪問(wèn)一個(gè)字段或者屬性時(shí)clr 需 要做更多的工作:校驗(yàn)參數(shù),檢查權(quán)限等等,所以速度是非常慢的。所以盡量不要使用反射進(jìn)行編程,對(duì)于打算編寫一個(gè)動(dòng)態(tài)構(gòu)造類型(晚綁定)的應(yīng)用程序,可以采取以下的幾種方式進(jìn)行代替: 
               
              1. 通過(guò)類的繼承關(guān)系。讓該類型從一個(gè)編譯時(shí)可知的基礎(chǔ)類型派生出來(lái),在運(yùn)行時(shí)生成該類 型的一個(gè)實(shí)例,將對(duì)其的引用放到其基礎(chǔ)類型的一個(gè)變量中,然后調(diào)用該基礎(chǔ)類型的虛方法。 
               
              2. 通過(guò)接口實(shí)現(xiàn)。在運(yùn)行時(shí),構(gòu)建該類型的一個(gè)實(shí)例,將對(duì)其的引用放到其接口類型的一個(gè)變量中,然后調(diào)用該接口定義的虛方法。 
               
              3.通過(guò)委托實(shí)現(xiàn)。讓該類型實(shí)現(xiàn)一個(gè)方法,其名稱和原型都與一個(gè)在編譯時(shí)就已知的委托相符。在運(yùn)行時(shí)先構(gòu)造該類型的實(shí)例,然后在用該方法的對(duì)象及名稱構(gòu)造出該委托的實(shí)例,接著通過(guò)委托調(diào)用你想要的方法。這個(gè)方法相對(duì)與前面兩個(gè)方法所作的工作要多一些,效率更低一些 


            -----------------------------------------------------------------------------------------------------------------------------------------------------

            反射技術(shù)
            我經(jīng)常在博客園看到運(yùn)用反射技術(shù)的***,可是遺憾自己一直不知道什么是反射,急忙找些資料學(xué)習(xí)學(xué)習(xí)。
            程序集包含模塊,而模塊包含類型,類型又包含成員。反射則提供了封裝程序集、模塊和類型的對(duì)象。您可以使用反射動(dòng)態(tài)地創(chuàng)建類型的實(shí)例,將類型綁定到現(xiàn)有對(duì)象,或從現(xiàn)有對(duì)象中獲取類型。然后,可以調(diào)用類型的方法或訪問(wèn)其字段和屬性。反射通常具有以下用途:
            使用 Assembly 定義和加載程序集,加載在程序集清單中列出的模塊,以及從此程序集中查找類型并創(chuàng)建該類型的實(shí)例。
            使用 Module 了解如下的類似信息:包含模塊的程序集以及模塊中的類等。您還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。
            使用 ConstructorInfo 了解如下的類似信息:構(gòu)造函數(shù)的名稱、參數(shù)、訪問(wèn)修飾符(如 public 或 private)和實(shí)現(xiàn)詳細(xì)信息(如 abstract 或 virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法來(lái)調(diào)用特定的構(gòu)造函數(shù)。
            使用 MethodInfo 來(lái)了解如下的類似信息:方法的名稱、返回類型、參數(shù)、訪問(wèn)修飾符(如 public 或 private)和實(shí)現(xiàn)詳細(xì)信息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法來(lái)調(diào)用特定的方法。
            使用 FieldInfo 來(lái)了解如下的類似信息:字段的名稱、訪問(wèn)修飾符(如 public 或 private)和實(shí)現(xiàn)詳細(xì)信息(如 static)等;并獲取或設(shè)置字段值。
            使用 EventInfo 來(lái)了解如下的類似信息:事件的名稱、事件處理程序數(shù)據(jù)類型、自定義屬性、聲明類型和反射類型等;并添加或移除事件處理程序。
            使用 PropertyInfo 來(lái)了解如下的類似信息:屬性的名稱、數(shù)據(jù)類型、聲明類型、反射類型和只讀或可寫狀態(tài)等;并獲取或設(shè)置屬性值。
            使用 ParameterInfo 來(lái)了解如下的類似信息:參數(shù)的名稱、數(shù)據(jù)類型、參數(shù)是輸入?yún)?shù)還是輸出參數(shù),以及參數(shù)在方法簽名中的位置等。
            舉例說(shuō)明:

            using System;

            using System.Reflection;



            namespace ReflectionExample

            {

                 
            class Class1

                 
            {

                     [STAThread]

                     
            static void Main(string[] args)

                     
            {

                          Console.WriteLine(
            "列出程序集中所有類型");

                          Assembly a 
            = Assembly.LoadFrom("ReflectionExample.exe");

                          Type[] mytypes 
            = a.GetTypes();

                          
            foreach(Type t in mytypes)

                          
            {

                               Console.WriteLine(t.Name);

                          }


                          Console.WriteLine(
            "列出HelloWorld中的所有方法");

                          Type ht 
            = typeof(HelloWorld);

                          MethodInfo[] mif 
            = ht.GetMethods();

                          
            foreach(MethodInfo mf in mif)

                          
            {

                               Console.WriteLine(mf.Name);

                          }


                          Console.WriteLine(
            "實(shí)例化HelloWorld,并調(diào)用HelloWorld方法");

                          Object obj 
            = Activator.CreateInstance(ht);

                          
            string[] s = {"wssmax"};

                          Object objName 
            = Activator.CreateInstance(ht,s);

                          MethodInfo msayhello 
            = ht.GetMethod("SayHello");

                          msayhello.Invoke(obj,
            null);

                          msayhello.Invoke(objName,
            null);

                          Console.ReadLine();

                     }


                 }


            }




            using System;



            namespace ReflectionExample

            {

                 
            public class HelloWorld

                 
            {

                     
            string myName;

                     
            public HelloWorld(string name)

                     
            {

                          myName 
            = name;

                     }


                     
            public HelloWorld():this(null)

                     
            {}

                     
            public string Name

                     
            {

                          
            get{return myName;}

                     }


                     
            public void SayHello()

                     
            {

                          
            if(myName == null)

                               Console.WriteLine(
            "Hello World");

                          
            else

                               Console.WriteLine(
            "Hello "+myName);

                     }


                 }


            }


            得到double類的信息:
            using System;
            using System.Text;
            using System.Windows.Forms;
            using System.Reflection;

            namespace Wrox.ProCSharp.TypeView
            {
                
            class MainClass
                
            {
                    
            static void Main()
                    
            {
                        
            // modify this line to retrieve details of any
                        
            // other data type
                        Type t = typeof(double);
               
                        AnalyzeType(t);
                        MessageBox.Show(OutputText.ToString(), 
            "Analysis of type " + t.Name);
                        Console.ReadLine();
                    }


                    
            static void AnalyzeType(Type t)
                    
            {
                        AddToOutput(
            "Type Name:  " + t.Name);
                        AddToOutput(
            "Full Name:  " + t.FullName);
                        AddToOutput(
            "Namespace:  " + t.Namespace);
                        Type tBase 
            = t.BaseType;
                        
            if (tBase != null)
                            AddToOutput(
            "Base Type:" + tBase.Name);
                        Type tUnderlyingSystem 
            = t.UnderlyingSystemType;
                        
            if (tUnderlyingSystem != null)
                            AddToOutput(
            "UnderlyingSystem Type:" + tUnderlyingSystem.Name);

                        AddToOutput(
            "\nPUBLIC MEMBERS:");
                        MemberInfo [] Members 
            = t.GetMembers();
                        
            foreach (MemberInfo NextMember in Members)
                        
            {
                            AddToOutput(NextMember.DeclaringType 
            + " " + NextMember.MemberType +
                                
            " " + NextMember.Name);
                        }

                    }


                    
            static void AddToOutput(string Text)
                    
            {
                        OutputText.Append(
            "\n" + Text);
                    }


                    
            static StringBuilder OutputText = new StringBuilder(500);
                }

            }

            posted on 2006-01-04 10:01 夢(mèng)在天涯 閱讀(26687) 評(píng)論(1)  編輯 收藏 引用 所屬分類: C#/.NET

            評(píng)論

            # re: c#的反射 2006-04-19 12:16 夢(mèng)在天涯

            關(guān)于反射

            提綱:
            1、什么是反射
            2、命名空間與裝配件的關(guān)系
            3、運(yùn)行期得到類型信息有什么用
            4、如何使用反射獲取類型
            5、如何根據(jù)類型來(lái)動(dòng)態(tài)創(chuàng)建對(duì)象
            6、如何獲取方法以及動(dòng)態(tài)調(diào)用方法
            7、動(dòng)態(tài)創(chuàng)建委托


            1、什么是反射
            Reflection,中文翻譯為反射。
            這是.Net中獲取運(yùn)行時(shí)類型信息的方式,.Net的應(yīng)用程序由幾個(gè)部分:‘程序集(Assembly)’、‘模塊(Module)’、‘類型(class)’組成,而反射提供一種編程的方式,讓程序員可以在程序運(yùn)行期獲得這幾個(gè)組成部分的相關(guān)信息,例如:

            Assembly類可以獲得正在運(yùn)行的裝配件信息,也可以動(dòng)態(tài)的加載裝配件,以及在裝配件中查找類型信息,并創(chuàng)建該類型的實(shí)例。
            Type類可以獲得對(duì)象的類型信息,此信息包含對(duì)象的所有要素:方法、構(gòu)造器、屬性等等,通過(guò)Type類可以得到這些要素的信息,并且調(diào)用之。
            MethodInfo包含方法的信息,通過(guò)這個(gè)類可以得到方法的名稱、參數(shù)、返回值等,并且可以調(diào)用之。
            諸如此類,還有FieldInfo、EventInfo等等,這些類都包含在System.Reflection命名空間下。

            2、命名空間與裝配件的關(guān)系
            很多人對(duì)這個(gè)概念可能還是很不清晰,對(duì)于合格的.Net程序員,有必要對(duì)這點(diǎn)進(jìn)行澄清。
            命名空間類似與Java的包,但又不完全等同,因?yàn)镴ava的包必須按照目錄結(jié)構(gòu)來(lái)放置,命名空間則不需要。

            裝配件是.Net應(yīng)用程序執(zhí)行的最小單位,編譯出來(lái)的.dll、.exe都是裝配件。

            裝配件和命名空間的關(guān)系不是一一對(duì)應(yīng),也不互相包含,一個(gè)裝配件里面可以有多個(gè)命名空間,一個(gè)命名空間也可以在多個(gè)裝配件中存在,這樣說(shuō)可能有點(diǎn)模糊,舉個(gè)例子:
            裝配件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{…}
            }

            這兩個(gè)裝配件中都有N1和N2兩個(gè)命名空間,而且各聲明了兩個(gè)類,這樣是完全可以的,然后我們?cè)谝粋€(gè)應(yīng)用程序中引用裝配件A,那么在這個(gè)應(yīng)用程序中,我們能看到N1下面的類為AC1和AC2,N2下面的類為AC3和AC4。
            接著我們?nèi)サ魧?duì)A的引用,加上對(duì)B的引用,那么我們?cè)谶@個(gè)應(yīng)用程序下能看到的N1下面的類變成了BC1和BC2,N2下面也一樣。
            如果我們同時(shí)引用這兩個(gè)裝配件,那么N1下面我們就能看到四個(gè)類:AC1、AC2、BC1和BC2。

            到這里,我們可以清楚一個(gè)概念了,命名空間只是說(shuō)明一個(gè)類型是那個(gè)族的,比如有人是漢族、有人是回族;而裝配件表明一個(gè)類型住在哪里,比如有人住在北京、有人住在上海;那么北京有漢族人,也有回族人,上海有漢族人,也有回族人,這是不矛盾的。

            上面我們說(shuō)了,裝配件是一個(gè)類型居住的地方,那么在一個(gè)程序中要使用一個(gè)類,就必須告訴編譯器這個(gè)類住在哪兒,編譯器才能找到它,也就是說(shuō)必須引用該裝配件。
            那么如果在編寫程序的時(shí)候,也許不確定這個(gè)類在哪里,僅僅只是知道它的名稱,就不能使用了嗎?答案是可以,這就是反射了,就是在程序運(yùn)行的時(shí)候提供該類型的地址,而去找到它。
            有興趣的話,接著往下看吧。

            3、運(yùn)行期得到類型信息有什么用
            有人也許疑問(wèn),既然在開(kāi)發(fā)時(shí)就能夠?qū)懞么a,干嘛還放到運(yùn)行期去做,不光繁瑣,而且效率也受影響。
            這就是個(gè)見(jiàn)仁見(jiàn)智的問(wèn)題了,就跟早綁定和晚綁定一樣,應(yīng)用到不同的場(chǎng)合。有的人反對(duì)晚綁定,理由是損耗效率,但是很多人在享受虛函數(shù)帶來(lái)的好處的時(shí)侯還沒(méi)有意識(shí)到他已經(jīng)用上了晚綁定。這個(gè)問(wèn)題說(shuō)開(kāi)去,不是三言兩語(yǔ)能講清楚的,所以就點(diǎn)到為止了。
            我的看法是,晚綁定能夠帶來(lái)很多設(shè)計(jì)上的便利,合適的使用能夠大大提高程序的復(fù)用性和靈活性,但是任何東西都有兩面性,使用的時(shí)侯,需要再三衡量。

            接著說(shuō),運(yùn)行期得到類型信息到底有什么用呢?
            還是舉個(gè)例子來(lái)說(shuō)明,很多軟件開(kāi)發(fā)者喜歡在自己的軟件中留下一些接口,其他人可以編寫一些插件來(lái)擴(kuò)充軟件的功能,比如我有一個(gè)媒體播放器,我希望以后可以很方便的擴(kuò)展識(shí)別的格式,那么我聲明一個(gè)接口:
            public interface IMediaFormat
            {
            string Extension {get;}
            Decoder GetDecoder();
            }
            這個(gè)接口中包含一個(gè)Extension屬性,這個(gè)屬性返回支持的擴(kuò)展名,另一個(gè)方法返回一個(gè)解碼器的對(duì)象(這里我假設(shè)了一個(gè)Decoder的類,這個(gè)類提供把文件流解碼的功能,擴(kuò)展插件可以派生之),通過(guò)解碼器對(duì)象我就可以解釋文件流。
            那么我規(guī)定所有的解碼插件都必須派生一個(gè)解碼器,并且實(shí)現(xiàn)這個(gè)接口,在GetDecoder方法中返回解碼器對(duì)象,并且將其類型的名稱配置到我的配置文件里面。
            這樣的話,我就不需要在開(kāi)發(fā)播放器的時(shí)侯知道將來(lái)擴(kuò)展的格式的類型,只需要從配置文件中獲取現(xiàn)在所有解碼器的類型名稱,而動(dòng)態(tài)的創(chuàng)建媒體格式的對(duì)象,將其轉(zhuǎn)換為IMediaFormat接口來(lái)使用。

            這就是一個(gè)反射的典型應(yīng)用。

            4、如何使用反射獲取類型
            首先我們來(lái)看如何獲得類型信息。
            獲得類型信息有兩種方法,一種是得到實(shí)例對(duì)象
            這個(gè)時(shí)侯我僅僅是得到這個(gè)實(shí)例對(duì)象,得到的方式也許是一個(gè)object的引用,也許是一個(gè)接口的引用,但是我并不知道它的確切類型,我需要了解,那么就可以通過(guò)調(diào)用System.Object上聲明的方法GetType來(lái)獲取實(shí)例對(duì)象的類型對(duì)象,比如在某個(gè)方法內(nèi),我需要判斷傳遞進(jìn)來(lái)的參數(shù)是否實(shí)現(xiàn)了某個(gè)接口,如果實(shí)現(xiàn)了,則調(diào)用該接口的一個(gè)方法:

            public void Process( object processObj )
            {
            Type t = processsObj.GetType();
            if( t.GetInterface(“ITest”) !=null )

            }

            另外一種獲取類型的方法是通過(guò)Type.GetType以及Assembly.GetType方法,如:
            Type t = Type.GetType(“System.String”);
            需要注意的是,前面我們講到了命名空間和裝配件的關(guān)系,要查找一個(gè)類,必須指定它所在的裝配件,或者在已經(jīng)獲得的Assembly實(shí)例上面調(diào)用GetType。
            本裝配件中類型可以只寫類型名稱,另一個(gè)例外是mscorlib.dll,這個(gè)裝配件中聲明的類型也可以省略裝配件名稱(.Net裝配件編譯的時(shí)候,默認(rèn)都引用了mscorlib.dll,除非在編譯的時(shí)候明確指定不引用它),比如:
            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");
            這樣才可以,大家可以看下面這個(gè)帖子:
            http://expert.csdn.net/Expert/topic/2210/2210762.xml?temp=.1919977
            qqchen的回答很精彩


            5、如何根據(jù)類型來(lái)動(dòng)態(tài)創(chuàng)建對(duì)象
            System.Activator提供了方法來(lái)根據(jù)類型動(dòng)態(tài)創(chuàng)建對(duì)象,比如創(chuàng)建一個(gè)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ù)的構(gòu)造器創(chuàng)建對(duì)象
            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”}; //構(gòu)造器參數(shù)
            TestClass obj = (TestClass)Activator.CreateInstance(t,constructParms);

            把參數(shù)按照順序放入一個(gè)Object數(shù)組中即可

            6、如何獲取方法以及動(dòng)態(tài)調(diào)用方法
            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;
            }
            }
            }
            }

            上面是一個(gè)簡(jiǎn)單的類,包含一個(gè)有參數(shù)的構(gòu)造器,一個(gè)GetValue的方法,一個(gè)Value屬性,我們可以通過(guò)方法的名稱來(lái)得到方法并且調(diào)用之,如:

            //獲取類型信息
            Type t = Type.GetType("TestSpace.TestClass");
            //構(gòu)造器的參數(shù)
            object[] constuctParms = new object[]{"timmy"};
            //根據(jù)類型創(chuàng)建對(duì)象
            object dObj = Activator.CreateInstance(t,constuctParms);
            //獲取方法的信息
            MethodInfo method = t.GetMethod("GetValue");
            //調(diào)用方法的一些標(biāo)志位,這里的含義是Public并且是實(shí)例方法,這也是默認(rèn)的值
            BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
            //GetValue方法的參數(shù)
            object[] parameters = new object[]{"Hello"};
            //調(diào)用方法,用一個(gè)object接收返回值
            object returnValue = method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null);

            屬性與方法的調(diào)用大同小異,大家也可以參考MSDN

            7、動(dòng)態(tài)創(chuàng)建委托
            委托是C#中實(shí)現(xiàn)事件的基礎(chǔ),有時(shí)候不可避免的要?jiǎng)討B(tài)的創(chuàng)建委托,實(shí)際上委托也是一種類型:System.Delegate,所有的委托都是從這個(gè)類派生的
            System.Delegate提供了一些靜態(tài)方法來(lái)動(dòng)態(tài)創(chuàng)建一個(gè)委托,比如一個(gè)委托:

            namespace TestSpace {
            delegate string TestDelegate(string value);
            public class TestClass {
            public TestClass() {
            }
            public void GetValue(string value) {
            return value;
            }
            }
            }

            使用示例:
            TestClass obj = new TestClass();

            //獲取類型,實(shí)際上這里也可以直接用typeof來(lái)獲取類型
            Type t = Type.GetType(“TestSpace.TestClass”);
            //創(chuàng)建代理,傳入類型、創(chuàng)建代理的對(duì)象以及方法名稱
            TestDelegate method = (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”);

            String returnValue = method(“hello”);

              回復(fù)  更多評(píng)論   

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計(jì)

            • 隨筆 - 461
            • 文章 - 4
            • 評(píng)論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1807602
            • 排名 - 5

            最新評(píng)論

            閱讀排行榜

            亚洲人成电影网站久久| 99精品国产在热久久| 欧美成人免费观看久久| 国产精品一区二区久久精品涩爱 | 久久成人精品视频| 亚洲乱亚洲乱淫久久| 久久综合给合综合久久| 久久午夜羞羞影院免费观看| 精品一久久香蕉国产线看播放| 久久成人永久免费播放| 麻豆一区二区99久久久久| 99国产欧美久久久精品蜜芽| 一本色道久久综合狠狠躁篇 | 日本精品久久久久久久久免费| 亚洲精品无码久久久久久| 国产69精品久久久久99| 亚洲中文字幕久久精品无码喷水| 91久久成人免费| 国产精品无码久久久久久| 亚洲人成网站999久久久综合 | 久久综合丝袜日本网| 伊人久久大香线蕉亚洲| 久久久亚洲精品蜜桃臀| 国产精品VIDEOSSEX久久发布| 色婷婷久久综合中文久久蜜桃av| 国产精品一区二区久久精品无码| 麻豆成人久久精品二区三区免费| 久久影视综合亚洲| 欧美麻豆久久久久久中文| 国产午夜精品理论片久久 | 精品久久人人爽天天玩人人妻| 色欲久久久天天天综合网| 亚洲精品午夜国产va久久| 久久这里有精品视频| 亚洲Av无码国产情品久久| 久久精品国产精品亚洲艾草网美妙| 色综合色天天久久婷婷基地| 久久精品一区二区三区不卡| 久久精品视频免费| 国产福利电影一区二区三区久久久久成人精品综合 | 欧美亚洲国产精品久久高清|