c#反射,反射程序員的快樂

1.什麼是反射?

我們先來看一張圖片吧。

c#反射,反射程序員的快樂

根據樹木的輪廓,我們在水中能得到,一棵一模一樣的樹木。好的,先帶大家簡單瞭解下,那麼,再程序中是如何體現呢!


反射是.NET中的重要機制,通過反射,可以在運行時獲得程序或程序集中每一個類型(包括類、結構、委託、接口和枚舉等)的成員和成員的信息。有了反射,即可對每一個類型瞭如指掌。另外我還可以直接創建對象,即使這個對象的類型在編譯時還不知道。

反射的用途:

(1)使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,以及從此程序集中查找類型並創建該類型的實例。

(2)使用Module瞭解包含模塊的程序集以及模塊中的類等,還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。

(3)使用ConstructorInfo瞭解構造函數的名稱、參數、訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等。

(4)使用MethodInfo瞭解方法的名稱、返回類型、參數、訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等。

(5)使用FiedInfo瞭解字段的名稱、訪問修飾符(如public或private)和實現詳細信息(如static)等,並獲取或設置字段值。

(6)使用EventInfo瞭解事件的名稱、事件處理程序數據類型、自定義屬性、聲明類型和反射類型等,添加或移除事件處理程序。

(7)使用PropertyInfo瞭解屬性的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等,獲取或設置屬性值。

(8)使用ParameterInfo瞭解參數的名稱、數據類型、是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。

反射用到的命名空間:

System.Reflection

System.Type

System.Reflection.Assembly

反射用到的核心類:

System.Type 類--通過這個類可以訪問任何給定數據類型的信息。

System.Reflection.Assembly類--它可以用於訪問給定程序集的信息,或者把這個程序集加載到程序中。

System.Type類:

System.Type 類對於反射起著核心的作用。但它是一個抽象的基類,Type有與每種數據類型對應的派生類,我們使用這個派生類的對象的方法、字段、屬性來查找有關該類型的所有信息。

獲取給定類型的Type引用有3種常用方式:

●使用 C# typeof 運算符。

Type t = typeof(string);

●使用對象GetType()方法。

string s = "helloWord";

Type t = s.GetType();

●還可以調用Type類的靜態方法GetType()。

Type t = Type.GetType("System.String");

上面這三類代碼都是獲取string類型的Type,在取出string類型的Type引用t後,我們就可以通過t來探測string類型的結構了。

string n = "helloWord";

Type t = n.GetType();

foreach (MemberInfo mi in t.GetMembers())

{

Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name);

}

Type類的屬性:

Name 數據類型名

FullName 數據類型的完全限定名(包括命名空間名)

Namespace 定義數據類型的命名空間名

IsAbstract 指示該類型是否是抽象類型

IsArray 指示該類型是否是數組

IsClass 指示該類型是否是類

IsEnum 指示該類型是否是枚舉

IsInterface 指示該類型是否是接口

IsPublic 指示該類型是否是公有的

IsSealed 指示該類型是否是密封類

IsValueType 指示該類型是否是值類型

Type類的方法:

GetConstructor(), GetConstructors():返回ConstructorInfo類型,用於取得該類的構造函數的信息

GetEvent(), GetEvents():返回EventInfo類型,用於取得該類的事件的信息

GetField(), GetFields():返回FieldInfo類型,用於取得該類的字段(成員變量)的信息

GetInterface(), GetInterfaces():返回InterfaceInfo類型,用於取得該類實現的接口的信息

GetMember(), GetMembers():返回MemberInfo類型,用於取得該類的所有成員的信息

GetMethod(), GetMethods():返回MethodInfo類型,用於取得該類的方法的信息

GetProperty(), GetProperties():返回PropertyInfo類型,用於取得該類的屬性的信息

可以調用這些成員,其方式是調用Type的InvokeMember()方法,或者調用MethodInfo, PropertyInfo和其他類的Invoke()方法。

查看類中的構造方法:

NewClassw nc = new NewClassw();

Type t = nc.GetType();

ConstructorInfo[] ci = t.GetConstructors(); //獲取類的所有構造函數

foreach (ConstructorInfo c in ci) //遍歷每一個構造函數

{

ParameterInfo[] ps = c.GetParameters(); //取出每個構造函數的所有參數

foreach (ParameterInfo pi in ps) //遍歷並打印所該構造函數的所有參數

{

Console.Write(pi.ParameterType.ToString()+" "+pi.Name+",");

}

Console.WriteLine();

}

用構造函數動態生成對象:

Type t = typeof(NewClassw);

Type[] pt = new Type[2];

pt[0] = typeof(string);

pt[1] = typeof(string);

//根據參數類型獲取構造函數

ConstructorInfo ci = t.GetConstructor(pt);

//構造Object數組,作為構造函數的輸入參數

object[] obj = new object[2]{"grayworm","hi.baidu.com/grayworm"};

//調用構造函數生成對象

object o = ci.Invoke(obj);

//調用生成的對象的方法測試是否對象生成成功

//((NewClassw)o).show();

用Activator生成對象:

Type t = typeof(NewClassw);

//構造函數的參數

object[] obj = new object[2] { "grayworm", "hi.baidu.com/grayworm" };

//用Activator的CreateInstance靜態方法,生成新對象

object o = Activator.CreateInstance(t,"grayworm","hi.baidu.com/grayworm");

//((NewClassw)o).show();

查看類中的屬性:

NewClassw nc = new NewClassw();

Type t = nc.GetType();

PropertyInfo[] pis = t.GetProperties();

foreach(PropertyInfo pi in pis)

{

Console.WriteLine(pi.Name);

}

查看類中的public方法:

NewClassw nc = new NewClassw();

Type t = nc.GetType();

MethodInfo[] mis = t.GetMethods();

foreach (MethodInfo mi in mis)

{

Console.WriteLine(mi.ReturnType+" "+mi.Name);

}

查看類中的public字段

NewClassw nc = new NewClassw();

Type t = nc.GetType();

FieldInfo[] fis = t.GetFields();

foreach (FieldInfo fi in fis)

{

Console.WriteLine(fi.Name);

} (http://hi.baidu.com/grayworm)

用反射生成對象,並調用屬性、方法和字段進行操作

NewClassw nc = new NewClassw();

Type t = nc.GetType();

object obj = Activator.CreateInstance(t);

//取得ID字段

FieldInfo fi = t.GetField("ID");

//給ID字段賦值

fi.SetValue(obj, "k001");

//取得MyName屬性

PropertyInfo pi1 = t.GetProperty("MyName");

//給MyName屬性賦值

pi1.SetValue(obj, "grayworm", null);

PropertyInfo pi2 = t.GetProperty("MyInfo");

pi2.SetValue(obj, "hi.baidu.com/grayworm", null);

//取得show方法

MethodInfo mi = t.GetMethod("show");

//調用show方法

mi.Invoke(obj, null);

System.Reflection.Assembly類

Assembly類可以獲得程序集的信息,也可以動態的加載程序集,以及在程序集中查找類型信息,並創建該類型的實例。

使用Assembly類可以降低程序集之間的耦合,有利於軟件結構的合理化。

通過程序集名稱返回Assembly對象

Assembly ass = Assembly.Load("ClassLibrary831");

通過DLL文件名稱返回Assembly對象

Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");

通過Assembly獲取程序集中類

Type t = ass.GetType("ClassLibrary831.NewClass"); //參數必須是類的全名

通過Assembly獲取程序集中所有的類

Type[] t = ass.GetTypes();

//通過程序集的名稱反射

Assembly ass = Assembly.Load("ClassLibrary831");

Type t = ass.GetType("ClassLibrary831.NewClass");

object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");

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);

}

}

最後整理下,反射在.net 中的機制。


c#反射,反射程序員的快樂

好啦,來輕鬆一下。

c#反射,反射程序員的快樂


分享到:


相關文章: