C 深入學習 反射

2021-10-03 03:32:56 字數 4638 閱讀 3955

目錄

一、概述

二、基本使用

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 作為日...