NET反射系統(tǒng)
2012-02-18 19:51 海不是藍(lán) 閱讀(564) 評論(0) 收藏 舉報(bào)沒事看書的筆記,雖然這些知識(shí)在項(xiàng)目中經(jīng)常用,但是系統(tǒng)的看看書也對得起這買書的錢。。。
|
Type |
查看msdn知道反射的所有東西都是在Reflection中,想獲取什么就去自己查查相關(guān)的類就好了,用了反射這么久,覺得其實(shí)核心就是那個(gè)Type。
Type派生于MemberInfo這個(gè)抽象類。其實(shí)想想,當(dāng)你獲取到了一個(gè)Type對象的時(shí)候,那么就應(yīng)該能點(diǎn)出什么得到這個(gè)對象的名稱,屬性,方法這些,所以整個(gè)反射系統(tǒng)都是這樣的,所以沒必要去每個(gè)類和方法都看,用的時(shí)候右鍵轉(zhuǎn)到定義看看就好。
static void Main(string[] args)
{
//不管什么,先得到Type
Type t = typeof(A);
Console.WriteLine("類型名稱:{0}", t.Name);
//得到類型中的字段集合,但是私有的字段不會(huì)被我們獲取到
//所以大牛們或者老師們都苦口良心的說重要私有的東西都private
Console.WriteLine();
FieldInfo[] fields = t.GetFields();
foreach (FieldInfo f in fields)
{
//FieldInfo還有很多東西,需要用的時(shí)候右鍵轉(zhuǎn)到定義看看就行
Console.WriteLine("{1} Field:{0}", f.Name, f.IsPublic ? "Public" : "Private");
}
//獲取下Type中的方法,有道詞典查查方法這個(gè)單詞,原來是method,那么應(yīng)該有個(gè)MethodInfo這個(gè)類吧
MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach (MethodInfo m in methods)
{
Console.Write("{0} {1}", m.IsPublic ? "Public" : "Private", m.Name);
//獲取下方法的參數(shù)
StringBuilder pstr = new StringBuilder();
ParameterInfo[] par = m.GetParameters();
foreach (ParameterInfo p in par)
{
pstr.AppendFormat(",{0} {1}", p.ParameterType.Name, p.Name);
}
Console.Write("({0})", pstr.ToString() != string.Empty ? pstr.ToString().Substring(1) : string.Empty);
//獲取返回值
Console.Write(" return {0}", m.ReturnType.Name);
Console.WriteLine();
}
Console.WriteLine();
Console.Read();
}
public class A
{
public string name;
public string name1;
private Int32 sum;
public void Show()
{
Console.WriteLine(this.name);
}
public static Int32 Test(Int32 i)
{
return i;
}
}

注意這里把基類object的方法成員也顯示了。
可以根據(jù)枚舉值來限定獲取的方法
public abstract MethodInfo[] GetMethods(BindingFlags bindingAttr);
獲取公開靜態(tài)的方法
MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static);
注意這里:假如只寫個(gè)公開的枚舉值,那么就無法獲取到方法,應(yīng)該至少包含 是否靜態(tài)或?qū)嵗杜e值和是否公開枚舉值。
|
反射調(diào)用方法 |
public abstract class MethodBase
public object Invoke(object obj, object[] parameters);
假如要調(diào)用的方法是實(shí)例方法,那么第一個(gè)參數(shù)就是對象,靜態(tài)方法就是null,后面的是參數(shù)集合。
static void Main(string[] args)
{
//不管什么,先得到Type
A a = new A();
Type t = a.GetType();
Console.WriteLine("類型名稱:{0}", t.Name);
//獲取下Type中的方法,有道詞典查查方法這個(gè)單詞,原來是method,那么應(yīng)該有個(gè)MethodInfo這個(gè)類吧
MethodInfo[] methods = t.GetMethods(BindingFlags.DeclaredOnly
| BindingFlags.Public | BindingFlags.Instance);//過濾掉父類的方法
foreach (MethodInfo m in methods)
{
//調(diào)用方法
if (m.Name == "Show")
m.Invoke(a, new object[] { "hello" });
Console.WriteLine();
}
Console.WriteLine();
Console.Read();
}
public class A
{
public void Show(string name)
{
Console.WriteLine(name);
}
}

|
調(diào)用構(gòu)造函數(shù)創(chuàng)建類型對象 |
前面的例子都是自己手動(dòng)創(chuàng)建個(gè)類型對象,這樣還不如直接去調(diào)用那些方法。
當(dāng)在有些特殊的需求中需要在運(yùn)行時(shí)來創(chuàng)建對象,這樣反射的優(yōu)勢就體現(xiàn)出來了。
反射創(chuàng)建對象其中的一個(gè)方法就是去調(diào)用類型的構(gòu)造函數(shù)。
注意這個(gè)方法返回的是object
public object Invoke(object[] parameters);
static void Main(string[] args)
{
//不管什么,先得到Type
A a = new A();
Type t = a.GetType();
Console.WriteLine("類型名稱:{0}", t.Name);
//獲取類型的構(gòu)造函數(shù),這里我們只需要?jiǎng)?chuàng)建一個(gè)默認(rèn)構(gòu)造函數(shù)的對象,所以構(gòu)造函數(shù)的參數(shù)為0
object obj = null;
ConstructorInfo[] Con = t.GetConstructors();
foreach (ConstructorInfo c in Con)
{
if (c.GetParameters().Length == 0)
{
obj = c.Invoke(null);
}
}
//現(xiàn)在我們將obj轉(zhuǎn)換成類型A
if (obj != null)
{
A a1 = obj as A;
a1.Show("abc");
}
else
Console.WriteLine("糟糕!");
Console.WriteLine();
Console.Read();
}
public class A
{
public void Show(string name)
{
Console.WriteLine(name);
}
}
|
通過程序集來獲取類型對象 |
前面的情況都是建立在我們知道A這個(gè)類,反射的功能是超級強(qiáng)大的,當(dāng)你不知道一個(gè)程序集中有那些類型對象,那么用反射去尋找程序集中的類型。
程序集這個(gè)類中有很多加載程序集的方法,請選擇最適合當(dāng)前情況的。
public static Assembly Load(string assemblyString);
public static Assembly LoadFile(string path);
public static Assembly LoadFrom(string assemblyFile);
上面這3個(gè)還有很多重載的方法,所以要具體去了解那么就去msdn看吧。
static void Main(string[] args)
{
//通過程序集獲取類型對象
Assembly asm = Assembly.Load("ConsoleApplication2");
Type[] type = asm.GetTypes();
foreach (Type t in type)
{
Console.WriteLine("類型名稱:{0}", t.Name);
}
Console.WriteLine();
Console.Read();
}
public class A
{
public void Show(string name)
{
Console.WriteLine(name);
}
}
public class B { }

到這里,其實(shí)你已經(jīng)想到了可以自己完成一個(gè)程序,比如全自動(dòng)類型查詢。
|
作者:海不是藍(lán) 博客:http://www.rzrgm.cn/hailan2012/ 郵箱:hailan2012@sina.com 本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。 |
浙公網(wǎng)安備 33010602011771號