C# 反射/對映學習
轉自:https://www.cnblogs.com/kingcat/archive/2007/09/03/879873.html
最近想研究一下反射,先上網找了找資料,幾乎大部分都是照抄MSDN的內容,生澀難懂,幾乎沒說,又找了找,發現一些強人的例項解析,才稍微有了點門道,個人感覺,反射其實就是為了能夠在程式執行期間動態的載入一個外部的DLL集合,然後通過某種辦法找到這個DLL集合中的某個空間下的某個類的某個成員(通過反射可以訪問該類所包含的所有成員,不論成員是公有還是私有),看看網上N人寫的例項:
1.運用反射呼叫其它程式集中的方法:
假設另一個工程中的所有類都編譯到一個dll檔案中了,在這很多的類當中,有一個類叫StringUtil,名稱空間在HSMP.CommonBasic.Common 程式碼如下 :
namespace lab.CommonBasic.Common
{
class StringUtil
{
public double GetSum(double x, double y)
{
return x + y;
}
}
}
編譯後dll檔案的存放路徑是:D:\Test\HSMP.CommonBasic.dll
現在的問題是,如何通過程式呼叫該dll檔案中的GetSum方法
大概有以下幾步:
//這裡要用LoadFrom,只有在本工程裡新增了該dll的引用後才可以使用Load
Assembly objAss = Assembly.LoadFrom(@"D:\Test\HSMP.CommonBasic.dll");
//HSMP.CommonBasic.Common.StringUtil類的全路徑
Type t = objAss.GetType("HSMP.CommonBasic.Common.StringUtil");
//動態生成類StringUtil的例項
object obj = System.Activator.CreateInstance(t);
//引數資訊,GetSum需要兩個int引數
System.Type[] paramTypes = new System.Type[2];
paramTypes[0] = System.Type.GetType("System.Int32");
paramTypes[1] = System.Type.GetType("System.Int32");
//找到對應的方法
MethodInfo p = t.GetMethod("SayHello", paramTypes);
// 也可以不給型別引數,下面呼叫時給實參就可以
MethodInfo p = t.GetMethod("SayHello");
//引數值,如果所呼叫的方法沒有引數,不用寫這些
Object[] parameters = new Object[2];
parameters[0] = 3;
parameters[1] = 4;
//如果沒有引數,寫null即可。
object objRetval = p.Invoke(obj, parameters);
通過程式碼可以看出反射其實很簡單。就是動態型別載入。 以上我們用反射對靜態型別做載入,但如果類是個範型類該怎麼辦呢?其實方法大同小異,只是獲取到型別時需要設定一下實際要使用的型別即可,先看範型類定義:
namespace lab.CommonBasic.Common
{
class StringUtil<T,U>
{
public string GetSum(T x, U y)
{
return x + " and " + y;
}
}
}
再看反射操作:
... 前面程式碼相同
//HSMP.CommonBasic.Common.StringUtil類的全路徑(範型類最後用 `2 標示需要2個範型型別引數)
Type t = objAss.GetType("HSMP.CommonBasic.Common.StringUtil`2");
// 這一步很重要,設定實際的範型型別
t = t.MakeGenericType(new Type[2] { typeof(string), typeof(string) });
//動態生成類StringUtil的例項
object obj = System.Activator.CreateInstance(t);
... 後面程式碼相同
還有一種情況,如果類是常類,但方法是範型方法改怎麼辦?非常簡單:
... 前面程式碼相同
//HSMP.CommonBasic.Common.StringUtil類的全路徑(範型類最後用 `2 標示需要2個範型型別引數)
Type t = objAss.GetType("HSMP.CommonBasic.Common.StringUtil`2");
// 這一步要去掉,因為類不是泛型類所以不能給類設定範型型別
//t = t.MakeGenericType(new Type[2] { typeof(string), typeof(string) });
... 中間程式碼相同 // 區別在這裡,把類級別的範型型別設定放到方法級別就可以了。 MethodInfo p = t.GetMethod("SayHello");
MethodInfo p = p.MakeGenericMethod(new Type[2] { typeof(string), typeof(string) });
... 後面程式碼相同
2.動態載入, 更改, 增加...某個程式集 下面例子中, ChangeValue類的myValue本是私有欄位, 一般情況下在類外部是不能改它的值的, 但利用反射就能直接訪問私有欄位而不需要通過包裝器
class ChangeValue
{
// 這是私有欄位
private string myValue;
// 一般只有通過這樣的公共屬性外面才可能訪問私有欄位
public ChangeValue(string str)
{
myValue = str;
}
public void WriteLine()
{
Console.WriteLine("MyValue is: " + myValue);
}
}
class Test
{
public static void Main(string[] args)
{
// 正常訪問
ChangeValue cv = new ChangeValue("old value");
cv.WriteLine();
//反射的方法直接訪問私有欄位
Type t = cv.GetType();
//得到私有欄位物件並賦值
FieldInfo field = t.GetField("myValue", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(cv, "new value");
//輸出的是新值 "new value"
cv.WriteLine();
}
}
打個比方, 你要寫一個播放器, 要支援如mp3, wmv, avi...等格式, 你還希望使用者能自己安裝一個新的格式, 也就是我們常說的外掛.
在實現這些, 可能你要將每種格式都寫成單個的解碼程式集, 如 mp3.dll, wmv.dll, avi.dll.... 這樣當播放時, 根據副檔名去動態呼叫相應的解碼程式集, 那麼這時你就得用反射去動態載入這些dll了.如: Assembly.LoadFile ("...avi.dll"), 然後通過反射可以用avi.dll裡面定義的類了.
原文請見:https://www.cnblogs.com/kingcat/archive/2007/09/03/879873.html
相關文章
- C#反射機制學習總結C#反射
- Mybatis學習筆記(5)-高階對映之多對多對映MyBatis筆記
- Mybatis學習筆記(4)-高階對映之一對多對映MyBatis筆記
- Mybatis學習筆記(3)—高階對映之一對一對映MyBatis筆記
- Scala學習(四)---對映和元組
- C#:DataTable對映成ModelC#
- C# 高效能物件對映C#物件
- .Net 反射學習反射
- Java學習:反射Java反射
- Java學習_反射Java反射
- Java反射學習Java反射
- MyBatis學習筆記(2)—對映關係篇MyBatis筆記
- JavaEE MyBatis關聯對映之多對多(教材學習筆記)JavaMyBatis筆記
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- 【C#】反射的用法及效率對比C#反射
- Erlang學習筆記(五)記錄與對映組筆記
- 學習Hibernate原始碼二_Hibernate物件對映檔案hbm學習原始碼物件
- java反射學習(一)Java反射
- C#反射C#反射
- Solidity語言學習筆記————17、原始檔對映Solid筆記
- rust學習九.3-集合之雜湊對映表Rust
- Java學習之反射篇Java反射
- Java學習筆記--反射Java筆記反射
- Go 反射 學習筆記Go反射筆記
- 好程式設計師Java學習路線分享mybatis對映程式設計師JavaMyBatis
- SpringMVC學習筆記9-靜態資源對映SpringMVC筆記
- Solidity語言學習筆記————16、對映MappingSolid筆記APP
- MyBatis學習 之 二、SQL語句對映檔案(1)resultMapMyBatisSQL
- C# 反射(Reflection)C#反射
- C#與Lua語言學習對比一C#
- Java學習筆記系列-反射Java筆記反射
- SpringMVC學習(三)對映請求引數&請求引數SpringMVC
- C# ORM從物件到資料庫表的對映C#ORM物件資料庫
- C#反射優化C#反射優化
- C# 反射詳解C#反射
- c# 反射呼叫方法C#反射
- java反射機制的學習心得Java反射