MemberInfo類中的只讀屬性 | |
屬性 |
描述 |
Type DeclaringType |
獲取聲明該成員的類或接口的類型 |
MemberTypes MemberType |
獲取成員的類型,這個值用于指示該成員是字段、方法、屬性、事件、或構造函數(shù) |
Int MetadataToken |
獲取與特定元數(shù)據相關的值 |
Module Module |
獲取一個代表反射類型所在模塊(可執(zhí)行文件)的Module對象 |
String Name |
成員的名稱 |
Type ReflectedType |
反射的對象類型 |
•MemberType屬性的返回類型為MemberTypes,這是一個枚舉,它定義了用于表示不同成員的類型值。這些值包括:MemberTypes.Constructor, MemberTypes.Method, MemberTypes.Field, MemberTypes.Event, MemberTypes.Property。因此可以通過檢查MemberType屬性來確定成員的類型,例如,在MemberType屬性的值為MemberTypes.Method時,該成員為方法
•MemberInfo類還包含兩個與特性相關的抽象方法:
1.GetCustomAttributes() :獲得與主調對象關聯(lián)的自定義特性列表。
2.IsDefined(): 確定是否為主調對象定義了相應的特性。
3.GetCustomAttributesData():返回有關自定義特性的信息(特性稍后便會提到)
當然除了MemberInfo類定義的方法和屬性外,Type類自己也添加了許多屬性和方法:如下表(只列出一些常用的,太多了,自己可以轉定義Type類看下)
Type類定義的方法 | |
方法 |
功能 |
ConstructorInfo[] GetConstructors() |
獲取指定類型的構造函數(shù)列表 |
EventInfo[] GetEvents(); |
獲取指定類型的時間列 |
FieldInfo[] GetFields(); |
獲取指定類型的字段列 |
Type[] GetGenericArguments(); |
獲取與已構造的泛型類型綁定的類型參數(shù)列表,如果指定類型的泛型類型定義,則獲得類型形參。對于正早構造的類型,該列表就可能同時包含類型實參和類型形參 |
MemberInfo[] GetMembers(); |
獲取指定類型的成員列表 |
MethodInfo[] GetMethods(); |
獲取指定類型的方法列表 |
PropertyInfo[] GetProperties(); |
獲取指定類型的屬性列表 |
Type類定義的屬性 | |
屬性 |
功能 |
Assembly Assembly |
獲取指定類型的程序集 |
TypeAttributes Attributes |
獲取制定類型的特性 |
Type BaseType |
獲取指定類型的直接基類型 |
String FullName |
獲取指定類型的全名 |
bool IsAbstract |
如果指定類型是抽象類型,返回true |
bool IsClass |
如果指定類型是類,返回true |
string Namespace |
獲取指定類型的命名空間 |
使用反射
上面的列術都是為了,這里的使用。
通過使用Type類定義的方法和屬性,我們能夠在運行時獲得類型的各種具體信息。這是一個非常強大的功能。我們一旦得到類型信息,就可以調用其構造函數(shù),方法,和屬性??梢?,反射是允許使用編譯時不可用的代碼的。
由于Reflection API非常多,這里不可能完整的介紹他們(這里如果完整的介紹,據說要一本書,厚書)。但是,Reflection API是按照一定邏輯設計的。因此,只要知道部分接口的使用方法,就可以舉一反三的使用剩余的接口。
這里我列出四種關鍵的反射技術:
1.獲取方法的信息
2.調用方法
3.構造對象
4.從程序集中加載類型
獲取方法的相關信息
一旦有了Type對象就可以使用GetMethodInfo()方法獲取此類型支持的方法列表。該方法返回一個MethodInfo 對象數(shù)組,MethodInfo對象描述了主調類型所支持的方法,他位于System.Reflection命名空間中
MethodInfo類派生于MethodBase抽象類,而MethodBase類繼承了MemberInfo類。因此我們能夠使用這三個類定義的屬性和方法。例如,使用Name屬性得到方法名稱。這里有兩個重要的成員:
1. ReturnType屬性 :為Type類型的對象,能夠提供方法的返回類型信息
2. GetParameters()方法 :返回參數(shù)列表,參數(shù)信息以數(shù)組形式保存在PatameterInfo對象中。PatameterInfo類定義了大量描述參數(shù)信息的屬性和方法。這里也列出兩個常用的屬性 :Name(包含參數(shù)名稱信息的字符串),ParameterType(參數(shù)類型的信息)。
下面代碼,我將使用反射獲得類中所支持的方法,還有方法的信息。
class MyClass
{
int x;
int y;
public MyClass(int i, int j)
{
x = i;
y = j;
}
public int sum()
{
return x + y;
}
public bool IsBetween(int i)
{
if (x i i y) return true;
else return false;
}
public void Set(int a, int b)
{
x = a;
y = b;
}
public void Set(double a, double b)
{
x = (int)a;
y = (int)b;
}
public void Show()
{
Console.WriteLine("x:{0},y:{1}",x,y);
}
}
class ReflectDemo
{
static void Main(string[] args)
{
Type t=typeof(MyClass); //獲取描述MyClass類型的Type對象
Console.WriteLine("Analyzing methods in "+t.Name); //t.Name="MyClass"
MethodInfo[] mi = t.GetMethods(); //MethodInfo對象在System.Reflection命名空間下。
foreach (MethodInfo m in mi) //遍歷mi對象數(shù)組
{
Console.Write(m.ReturnType.Name); //返回方法的返回類型
Console.Write(" " + m.Name + "("); //返回方法的名稱
ParameterInfo[] pi = m.GetParameters(); //獲取方法參數(shù)列表并保存在ParameterInfo對象數(shù)組中
for (int i = 0; i pi.Length; i++)
{
Console.Write(pi[i].ParameterType.Name); //方法的參數(shù)類型名稱
Console.Write(" "+pi[i].Name); // 方法的參數(shù)名
if (i + 1 pi.Length)
{
Console.Write(", ");
}
}
Console.Write(")");
Console.WriteLine(); //換行
}
Console.ReadKey();
}
}
bool Equals(object obj) int GetHashCode() Type GetType() string ToString()
注意:這里輸出的除了MyClass類定義的所有方法外,也會顯示object類定義的共有非靜態(tài)方法。這是因為c#中的所有類型都繼承于object類。另外,這些信息實在程序運行時動態(tài)獲得的,并不需要預先知道MyClass類的定義
GetMethods()方法的另一種形式
這種形式可以制定各種標記,已篩選想要獲取的方法。他的通用形式為:MethodInfo[] GetMethods(BindingFlags bindingAttr)
BindingFlags是一個枚舉,枚舉值有(很多只列出5個吧):
1.DeclareOnly:僅獲取指定類定義的方法,而不獲取所繼承的方法;
2.Instance:獲取實例方法
3.NonPublic: 獲取非公有方法
4.Public: 獲取共有方法
5.Static:獲取靜態(tài)方法
GetMethods(BindingFlags bindingAttr)這個方法,參數(shù)可以使用or把兩個或更多標記連接在一起,實際上至少要有Instance(或Static)與Public(或NonPublic)標記。否則將不會獲取任何方法。
class MyClass
{
int x;
int y;
public MyClass(int i, int j)
{
x = i;
y = j;
}
private int sum()
{
return x + y;
}
public bool IsBetween(int i)
{
if (x i i y) return true;
else return false;
}
public void Set(int a, int b)
{
x = a;
y = b;
}
public void Set(double a, double b)
{
x = (int)a;
y = (int)b;
}
public void Show()
{
Console.WriteLine("x:{0},y:{1}",x,y);
}
}
class ReflectDemo
{
static void Main(string[] args)
{
Type t=typeof(MyClass); //獲取描述MyClass類型的Type對象
Console.WriteLine("Analyzing methods in "+t.Name); //t.Name="MyClass"
MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Public); //不獲取繼承方法,為實例方法,為公開的
foreach (MethodInfo m in mi) //遍歷mi對象數(shù)組
{
Console.Write(m.ReturnType.Name); //返回方法的返回類型
Console.Write(" " + m.Name + "("); //返回方法的名稱
ParameterInfo[] pi = m.GetParameters(); //獲取方法參數(shù)列表并保存在ParameterInfo對象數(shù)組中
for (int i = 0; i pi.Length; i++)
{
Console.Write(pi[i].ParameterType.Name); //方法的參數(shù)類型名稱
Console.Write(" "+pi[i].Name); // 方法的參數(shù)名
if (i + 1 pi.Length)
{
Console.Write(", ");
}
}
Console.Write(")");
Console.WriteLine(); //換行
}
Console.ReadKey();
}
}
使用反射調用方法
上面我們通過反射獲取到了類中的所有信息,下面我們就再使用反射調用通過反射獲取到的方法。
要調用反射獲取到的方法,則需要在MethodInfo實例上調用Invoke() 方法。Invoke()的使用,在下面例子中演示,說明。
下面例子是:先通過反射獲取到要調用的方法,然后使用Invoke()方法,調用獲取到的指定方法;
class MyClass
{
int x;
int y;
public MyClass(int i, int j)
{
x = i;
y = j;
}
private int sum()
{
return x + y;
}
public bool IsBetween(int i)
{
if (x i i y) return true;
else return false;
}
public void Set(int a, int b)
{
Console.Write("Inside set(int,int).");
x = a;
y = b;
Show();
}
public void Set(double a, double b)
{
Console.Write("Inside set(double,double).");
x = (int)a;
y = (int)b;
Show();
}
public void Show()
{
Console.WriteLine("x:{0},y:{1}", x, y);
}
}
class InvokeMethDemo
{
static void Main()
{
Type t=typeof(MyClass);
MyClass reflectOb = new MyClass(10, 20);
reflectOb.Show(); //輸出為: x:10, y:20
MethodInfo[] mi = t.GetMethods();
foreach (MethodInfo m in mi)
{
ParameterInfo[] pi = m.GetParameters();
if (m.Name.Equals("Set", StringComparison.Ordinal) pi[0].ParameterType == typeof(int))
{
object[] args = new object[2];
args[0] = 9;
args[1] = 10;
//參數(shù)reflectOb,為一個對象引用,將調用他所指向的對象上的方法,如果為靜態(tài)方法這個參數(shù)必須設置為null
//參數(shù)args,為調用方法的參數(shù)數(shù)組,如果不需要參數(shù)為null
m.Invoke(reflectOb, args); //調用MyClass類中的參數(shù)類型為int的Set方法,輸出為Inside set(int,int).x:9, y:10
}
}
Console.ReadKey();
}
}
class MyClass
{
int x;
int y;
public MyClass(int i)
{
x = y + i;
}
public MyClass(int i, int j)
{
x = i;
y = j;
}
public int sum()
{
return x + y;
}
}
class InvokeConsDemo
{
static void Main()
{
Type t = typeof(MyClass);
int val;
ConstructorInfo[] ci = t.GetConstructors(); //使用這個方法獲取構造函數(shù)列表
int x;
for (x = 0; x ci.Length; x++)
{
ParameterInfo[] pi = ci[x].GetParameters(); //獲取當前構造函數(shù)的參數(shù)列表
if (pi.Length == 2) break; //如果當前構造函數(shù)有2個參數(shù),則跳出循環(huán)
}
if (x == ci.Length)
{
return;
}
object[] consargs = new object[2];
consargs[0] = 10;
consargs[1] = 20;
object reflectOb = ci[x].Invoke(consargs); //實例化一個這個構造函數(shù)有兩個參數(shù)的類型對象,如果參數(shù)為空,則為null
//實例化后,調用MyClass中的方法
MethodInfo[] mi = t.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
foreach (MethodInfo m in mi)
{
if (m.Name.Equals("sum", StringComparison.Ordinal))
{
val = (int)m.Invoke(reflectOb, null); //由于實例化類型對象的時候是用的兩個參數(shù)的構造函數(shù),所以這里返回的結構為30
Console.WriteLine(" sum is " + val); //輸出 sum is 30
}
}
Console.ReadKey();
}
}
借助Reflection API,可以加載程序集,獲取它的相關信息并創(chuàng)建其公共可用類型的實例。通過這種機制,程序能夠搜索其環(huán)境,利用潛在功能,而無需在編譯期間顯式的定義他們。這是一個非常有效,且令人興奮的概念。
為了說明如何獲取程序集中的類型,我創(chuàng)建兩個文件。第一個文件定義一組類,第二個文件則反射各個類的信息。 代碼效果如下。
1.這下面代碼是要編譯生成MyClass.exe文件的
class MyClass
{
int x;
int y;
public MyClass(int i)
{
x = y + i;
}
public MyClass(int i, int j)
{
x = i;
y = j;
}
public int sum()
{
return x + y;
}
}
class Demo
{
static void Main()
{
Console.WriteLine("hello word !");
Console.ReadKey();
}
}
class Class3
{
static void Main() {
Assembly asm = Assembly.LoadFrom(@"C:\Users\lenovo\Documents\visual studio 2010\Projects\Reflection_test\ConsoleApplication1\bin\Debug\MyClass.exe"); //加載指定的程序集
Type[] alltype = asm.GetTypes(); //獲取程序集中的所有類型列表
foreach (Type temp in alltype)
{
Console.WriteLine(temp.Name); //打印出MyClass程序集中的所有類型名稱 MyClass , Demo
}
Console.ReadKey();
}
}
標簽:喀什 新鄉(xiāng) 百色 朝陽 朔州 周口 臺州 洛陽
巨人網絡通訊聲明:本文標題《.net中 關于反射的詳細介紹》,本文關鍵詞 .net,中,關于,反射,的,詳細,;如發(fā)現(xiàn)本文內容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內容系統(tǒng)采集于網絡,涉及言論、版權與本站無關。