目錄
一、概述
二、基本使用
2.1 獲取程式類容基本步驟
2.2 使用舉例
2.2.1 建立物件&訪問設定屬性值&使用其中無參方法
2.2.2 建立帶參建構函式並訪問其中帶參方法
2.2.3 反射過載過的方法
2.2.4 反射泛型類和泛型方法
2.2.5 反射型別中的私有類容(屬性&方法&...)
2.2.6 反射型別中的attribute
三 、反射特點
我們之所以能看見這個世界萬事萬物,不是萬物能發光,而是因為它們反**太陽的光芒。在c#**世界裡,我們的**被編譯為乙個個dll和exe ,同樣,也有這樣一束光能讓我們看清dll和exe中我們定義的各個類/屬性等等一切。這束光就是 using system.reflection; 看清並使用裡面的內容的過程就是反射。
a. 引導程式集
b.獲得程式集中型別
c.獲得其中屬性/方法/字段
基本操作**如下
引導程式集,可以指定完整路徑,否則從當前執行目錄尋找
assembly assembly = assembly.load("xiaomitv");
//第二步,獲取程式中所有的型別type
type types = assembly.gettypes(); //獲取程式集中所有的type,也就是程式集中包含的所有c#型別(類,介面,委託,結構...)
type type = assembly.gettype("xiaomitv.xiaomi"); //獲取指定type名稱(包含命名空間)的type
//第三步,獲取type中的類容
propertyinfo props = type.getproperties(); //獲得type中的所有屬性
var prop = type.getproperty("propname"); //根據指定名稱獲取屬性
fieldinfo fields = type.getfields(); //獲取type中的所有字段
fieldinfo field = type.getfield("fildname"); //根據指定名稱獲取字段
methodinfo methods = type.getmethods(); //獲取type中所有方法
methodinfo method = type.getmethod("methodname"); //根據指定名稱獲取方法
}
var assembly = assembly.load("xiaomitv");
var type = assembly.gettype("xiaomitv.xiaomi");
/** 建立物件例項
* createinstance(type type,params object args)
* 引數:type => 要建立例項的型別
* params object => 構造函式引數組,無參構造傳入null
*/object objtv = activator.createinstance(type, null);
// objtv.id = 5; // 編譯報錯,object 並沒有id屬性
var prop = type.getproperty("id"); // 根據id獲取 id屬性
prop.setvalue(objtv, 5); // 設定objtv物件中id屬性值
var propvalue = prop.getvalue(objtv); // 獲取objtv物件中id屬性值
var show = type.getmethod("show"); //獲取type中的show方法
/* * 執行show方法
* xxmethod.invoke(object obj,object args)
* 引數:
* object obj =>該方法執行載體,在哪個具體例項中執行
* object args =>執行該方法的引數組,無引數則為null
*/show.invoke(objtv, null);
注意事項:
1. activator.createinstance(type,null);返回的是object物件,無法直接訪問id屬性,可以轉換如下,但是不推薦。後續文章會有專門的解決方案
//用dynamic 替換 object ,躲過編譯器檢查
//但是會出現安全問題,如果選擇了乙個不存在的屬性,執行的時候就報錯
dynamic dynamictv = activator.createinstance(type, null);
dynamictv.id = 3;
2. xxmethod.invoke(object obj,object args); obj 引數,執行載體,其實就是為這個方法提供執行上下文。執行上下文不一樣,結果可能會不一樣(如果它用到載體中的一些元素)
3. prop.setvalue() 和 prop.getvalue() 一定要指定到具體物件例項
); //帶乙個string型別的構造引數
var shutdown = type.getmethod("shutdown");
var re = shutdown.invoke(obj, new object ); // 帶乙個int型別的方法
}
注意事項:
1. 我只舉例單個引數,多個引數的話,直接在 new object{}中依次新增。
2. 若方法有返回值,直接也可以獲取,不過是 object型別,使用的是後進行強轉。
就是在尋找方法的時候加上過載型別如下:
/* 反射如下reload的方法
* public void reload(string name,int sec);
*/var reload = type.getmethod("reload", new type );
/* 反射如下reload的方法
* public void reload(int sec);
*/var reload1 = type.getmethod("reload", new type );
var assembly = assembly.load("xiaomitv");
var generictype = assembly.gettype("xiaomitv.generict`1") //`1 表示該類有乙個佔位(泛型引數)
.makegenerictype(new type ); //表示要建立物件例項時傳入的指定型別為int
var genericmethod = generictype.getmethod("methtest")
.makegenericmethod(new type ); //指定呼叫該方法傳入的泛型型別為string
genericmethod.invoke(generictype, new object ); //呼叫泛型方法
注意事項:
1. 佔位符用 `2 表示有兩個泛型型別。「`」 是鍵盤第二排第乙個英文狀態下的符號。
2.在指定泛型具體型別時候要注意和原物件泛型順序一致。
var methodshow = typesingleton.getmethod("show",bindingflags.nonpublic | bindingflags.instance);
就是在 get*** 方法中新增 bindingflags 選項。還有很多其他選項,需要的時候可以看看
var assembly = assembly.load("xiaomitv");
var type = assembly.gettype("xiaomitv.xiaomi");
ienumerabletypeattrs = type.getcustomattributes(); //獲取物件上的所有attribute
var prop = type.getproperty("id");
ienumerablepropattrs = prop.getcustomattributes(); //獲取屬性上的所有attribute
var method = type.getmethod("show");
ienumerablemethodattrs = method.getcustomattributes(); //獲取方法上的所欲attribute
注意事項:
xx.getcustomattibutes中獲取乙個列舉型別的結果,然後可以進一步處理(下面章節attribut會提到)
1.動態載入dll,根據字串就可以建立物件例項並使用,減少了物件間依賴
2.突破私有許可權,可以訪問私有內容(方法$屬性...)
3.效能較差
深入學習C 利用反射給物件賦值
c 中利用反射能夠獲取物件的屬性資訊,也可以利用反射給物件賦值。我們如果想利用凡是給乙個物件屬性賦值可以通過propertyinfo.setvalue 方式進行賦值,但要注意值的型別要與屬性保持一致。假設我們有如下乙個結構 struct person public string name 下面一段 ...
深入學習C 利用反射給物件賦值
c 中利用反射能夠獲取物件的屬性資訊,也可以利用反射給物件賦值。我們如果想利用凡是給乙個物件屬性賦值可以通過propertyinfo.setvalue 方式進行賦值,但要注意值的型別要與屬性保持一致。假設我們有如下乙個結構 struct person public string name 下面一段 ...
深入學習c 書單
本來有一本c 程式設計,一本c primer 沒怎麼看過 經過師兄推薦又買了effective c 和more effective c 技術面試的時候會問的比較深 要研究的比較透徹一些 第一篇一些同學問我,如何學好c 我沒有別的辦法給你們,唯一的辦法就是讀書,讀大 量的書,就可以解決。要把c 作為日...