概念
反射機(jī)制是使程序具有動態(tài)特性的非常關(guān)鍵的一種機(jī)制
需求1:根據(jù)指定的類名梦碗,類字段名和所對應(yīng)的數(shù)據(jù),得到該類的實例担神。
需求2:根據(jù)指定的裝箱對象 獲取其屬性值或者調(diào)用其方法
需求3:獲取未來會產(chǎn)生的程序集 并使用其中的類
讓我們可以于運(yùn)行時加載黄选、探知、使用編譯期間完全未知的classes际插。換句話說,程序可以加載一個運(yùn)行時才得知名稱的class,獲悉其完整構(gòu)造(但不包括methods定義)率寡,并生成其對象實體、或?qū)ζ鋐ields設(shè)值倚搬、或喚起其methods1勇劣。
反射需要的類
反射用到的命名空間:
???System.Reflection
???System.Type
???System.Reflection.Assembly
???(1)使用Assembly定義和加載程序集,加載在程序集清單中列出模塊潭枣,以及從此程序集中查找類型并創(chuàng)建該類型的實例比默。 ???
? ?(2)使用Type這個類可以訪問任何給定數(shù)據(jù)類型的信息。
???(3)使用ConstructorInfo了解構(gòu)造函數(shù)的名稱盆犁、參數(shù)命咐、訪問修飾符(如pulic 或private)和實現(xiàn)詳細(xì)信息(如abstract或virtual)等。
???(4)使用MethodInfo了解方法的名稱谐岁、返回類型醋奠、參數(shù)、訪問修飾符(如pulic 或private)和實現(xiàn)詳細(xì)信息(如abstract或virtual)等伊佃。
???(5)使用FiedInfo了解字段的名稱窜司、訪問修飾符(如public或private)和實現(xiàn)詳細(xì)信息(如static)等,并獲取或設(shè)置字段值航揉。
???(6)使用PropertyInfo了解屬性的名稱塞祈、數(shù)據(jù)類型、聲明類型帅涂、反射類型和只讀或可寫狀態(tài)等议薪,獲取或設(shè)置屬性值尤蛮。
System.Type類:
???System.Type 類對于反射起著核心的作用。但它是一個抽象的基類斯议,Type有與每種數(shù)據(jù)類型對應(yīng)的派生類产捞,我們使用這個派生類的對象的方法、字段哼御、屬性來查找有關(guān)該類型的所有信息坯临。
???獲取給定類型的Type引用有3種常用方式:
???●使用 C# typeof 運(yùn)算符。已知類型
???????Type t = typeof(string);
???●使用對象GetType()方法恋昼。 已知對象
???????string s = "grayworm";
???????Type t = s.GetType();
???●還可以調(diào)用Type類的靜態(tài)方法GetType()看靠。已知類名
???????Type t = Type.GetType("System.String");
反射生成的對象
1.用Type構(gòu)建對象
用構(gòu)造函數(shù)動態(tài)生成對象:
既然有反射 那就有“正射”
對比一下:
有一個class Test ?有無參構(gòu)造方法
獲取實例的比較:
“正” :由類名直接使用關(guān)鍵字new來獲得 語法:new Test()
反射:未知類名 運(yùn)行時獲得類型名:例如:Type?type?=?Type.GetType("Test");
???Object o = type.GetConstructor (new Type[]{}).Invoke (null);
??當(dāng)然參數(shù)也可以由配置文件獲得
以上調(diào)用無參構(gòu)造 帶參的構(gòu)造怎么調(diào)用呢?
2.用Activator生成對象:
???? ?Type t = typeof(NewClassw);
???????//構(gòu)造函數(shù)的參數(shù)
???????object[] obj = new object[2] { "實參1", "實參2" }; ??
???????//用Activator的CreateInstance靜態(tài)方法焰雕,生成新對象
???????object o = Activator.CreateInstance(t,obj);
3.Assembly生成對象:
Assembly assembly = Assembly.Load ("ReflectTest");
Object obj = assembly.CreateInstance ("ReflectTest.Wood");
反射獲取字段值
一般用于已知對象時使用
同樣用正反來做對比:
已知對象MyClass obj
對象內(nèi)有name這個字段
正:
obj.name = "xxx"即可設(shè)置該對象的值
obj.name即可獲得該對象的值
反射:
//獲取類的描述對象
Type t = obj.GetType();
//取得字段描述對象
FieldInfo fi = t.GetField("name");
//獲取或設(shè)置字段值
fi.SetValue(obj, "k001");
fi.GetValue(obj);
一般在C#中以屬性替代字段
//獲取類的描述對象
Type t = obj.GetType();
//取得屬性描述對象
PropertyInfo pi1 = t.GetProperty("Name");
//獲取或設(shè)置屬性值
pi1.SetValue(obj, "k001",null);
pi1.GetValue(obj,null);
反射執(zhí)行方法
一般用于對象衷笋、方法名、參數(shù)類型已知
對象:obj?
方法名:methodName
參數(shù)類型 String int
正:
直接給予參數(shù)調(diào)用:obj.methodName("實參1"矩屁,實參2(int))
反射:
//獲取類的描述對象
Type t = obj.GetType();
//取得方法描述對象
MethodInfo mi = t.GetMethod("show");
//調(diào)用方法
mi.Invoke(obj, "實參1"辟宗,實參2(int));
參數(shù)可以換成數(shù)組
動態(tài)載入程序集
System.Reflection.Assembly類
????Assembly類可以獲得程序集的信息,也可以動態(tài)的加載程序集吝秕,以及在程序集中查找類型信息泊脐,并創(chuàng)建該類型的實例。
???使用Assembly類可以降低程序集之間的耦合烁峭,有利于軟件結(jié)構(gòu)的合理化容客。
???通過程序集名稱返回Assembly對象
???????Assembly ass = Assembly.Load("ClassLibrary831");
???通過DLL文件名稱返回Assembly對象
???????Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");
???通過Assembly獲取程序集中類
???????Type t = ass.GetType("ClassLibrary831.NewClass"); ??//參數(shù)必須是類的全名
???通過Assembly獲取程序集中所有的類
???????Type[] t = ass.GetTypes();
???//通過程序集的名稱反射
???Assembly ass = Assembly.Load("ClassLibrary831");
???Type t = ass.GetType("ClassLibrary831.NewClass");
???object o = Activator.CreateInstance(t, "", "");
???MethodInfo mi = t.GetMethod("show");
???mi.Invoke(o, null);
??//通過DLL文件全名反射其中的所有類型
???Assembly assembly = Assembly.LoadFrom("xxx.dll的路徑");
???Type[] aa = a.GetTypes();
???foreach(Type t in aa)
???{
???????if(t.FullName == "a.b.c")
???????{
???????????object o = Activator.CreateInstance(t);
???????}
???}
小結(jié)
反射屬于面向?qū)ο蟮膭討B(tài)補(bǔ)充
讓C#的面向?qū)ο笞龅?所見即所得"