反射手冊筆記 3 使用物件

2022-01-31 16:43:41 字數 4916 閱讀 4173

本章是上一章的繼續,再獲取到物件型別後,接下來做的事情。

第一部分 動態呼叫成員——呼叫方法,檢索或更改屬性,以及字段

方法1:利用info類呼叫類成員

1.用methodinfo類呼叫方法:

object invoke(object obj, object parameters)

其中,第1個引數obj,是物件的例項(靜態方法相應引數為null);第2個引數parameters是要傳遞到方法中的引數陣列;返回值為object型別,因此,要對結果進行強制型別轉換。示例如下:

public

class

mathclass

[stathread]

static

void

main()

;methodinfo method 

=objmath.gettype().getmethod(

"multiply");

intresult =(

int)method.invoke(objmath, paramarray);}}

其中,objmath.gettype()

.getmethod(

"multiply

")方法,預設搜尋所有共有成員,可以使用其過載方法:

objmath.gettype()

.getmethod(

"multiply

", bindingflag.nonpublic),從而獲取非公有成員。

2.用propertyinfo類呼叫屬性:

getvalue(object obj, object index)

setvalue(object obj, object newvalue, object index)

其中,index為索引器(靜態設為null),obj為物件的例項(靜態設為null),返回值同樣為object型別。示例如下:

public

class

human

set}

[stathread]

static

void

main()

}3.用fieldinfo類呼叫字段:

getvalue(object obj)

setvalue(object obj, object value)

fieldinfo類使用同propertyinfo,只是沒有index罷了。示例略。

方法2:利用invokemember()方法呼叫類成員

3個過載,最常用的如下:

object invokemember(

string

name,                    

//要呼叫的物件名:可以是屬性名/方法名/欄位名

bindingflags invokeattr,        

//搜尋成員的條件,以及如何處理第乙個引數:

//如bindingflags.invokemethod表示第乙個引數為方法名;

或setproperty

表示第乙個引數為屬性名;

或getfield

表示第乙個引數為欄位名;

binder binder,                  

//一般設為null,則會使用預設的defaultbinder,對提供的引數進行型別轉換,從原型別轉為目標型別

object target,                  

//呼叫成員的型別的例項(靜態成員為null)

object args                   

//對方法而言,是方法引數陣列;對欄位/屬性而言,獲取時是null,設定時是newvalue

);      

1.呼叫方法:

methodinfo類的invoke()方法,不能直接處理過載方法,即無法判斷使用哪個過載方法,而invokemember則可以自動找到匹配的過載方法。示例如下:

type mathtype 

=typeof

(system.math);

object

paramarray =;

intresult =(

int)mathtype.invokemember(

"max",

bindingflags.public 

|bindingflags.invokemethod 

|bindingflags.static,

null

, null

, paramarray);

當然,如果使用methodinfo類的invoke()方法處理過載方法,要輔助以selectmethod()先找到對應的過載方法,然後才能呼叫。

2.操縱屬性

得到屬性用bindingflags.getproperty,同時引數陣列為null;設定屬性用bindingflags.setproperty,示例如下:

type humantype 

=typeof

(human);

human newhuman 

=new

human();

//設定私有屬性name

object

paramarray =;

humantype.invokemember(

"name",

bindingflags.nonpublic 

|bindingflags.instance 

|bindingflags.setproperty, 

null

, newhuman, paramarray);

//得到私有屬性name型別物件

string

result 

=humantype.invokemember(

"get_name",

bindingflags.nonpublic 

|bindingflags.instance 

|bindingflags.invokemethod, 

null

, newhuman, 

null

);補注:

在msil中屬性其實就是方法,所以對屬性的操縱也可以使用如下方式(以get為例):

humantype.invokemember(

"get_name",

bindingflags.nonpublic 

|bindingflags.instance 

|bindingflags.invokemethod, 

null

, newhuman, 

null

);            同理,可以使用methodinfo.invokemethod()改寫為:

human objhuman 

=new

human();

object paramarray =;

methodinfo method 

=objhuman.gettype().getmethod(

"get_name");

string

result =(

string

)method.invoke(objhuman, paramarray);

3.操縱字段

基本上同於"操縱屬性",不再多言。

兩種方法的比較:

type的invokemember()方法靈活且功能強大,應該優先使用;僅當需要處理元資料時,才使用info類。

第二部分 用反射模擬委託功能

之所以要模擬,是因為委託時型別安全的(編譯期)——區別於反射(執行期),所以小型程式要盡量使用委託。

委託不區分靜態方法/例項方法——區別於反射。

模擬**如下:

public

class

invoker

public

invoker(object targetobject, string targetmethod)

public

object invoke(object args)

else

return

mytype.invokemember(mymethod, mybindingflags, 

null

, myobject, args);

}else}}

public

class

mymath

public

intmultiply(

intx, 

inty)

static

void

main()

;mymath objmath 

=new

mymath();

invoker mydelegate 

=new

invoker(objmath, 

"multiply");

result 

=mydelegate.invoke(args);

console.writeline(

"the product of  and  is: 

", args[

0], args[

1], result);

invoker objdelegate 

=new

invoker(

typeof

(mymath), 

"pow");

result 

=objdelegate.invoke(args);

console.writeline(

"the product of  and  is: 

", args[

0], args[

1], result);

}catch}}

在模擬中,委託可以使用委託鏈實現"反射"過載方法。

pythond物件 異常 反射的學習筆記

python多繼承,剛開始我是表示驚訝的,畢竟學的php,哪來的多繼承?頂多也就是利用介面模擬多繼承後者使用反射機制實現。那麼還是來看看python的強大吧 1 首先,python的類繼承了多個類,那麼其尋找方法的方式有兩種,分別是 深度優先 經典類 和廣度優先 新式類 class 經典類 唯一的區...

使用反射進行物件例項化

使用反射進行物件例項化 使用反射進行物件例項化,不再使用new關鍵字 1.第一種,使用.properties配置檔案建立物件 首先需要乙個實體類 public class phone 接下來新建乙個資料夾rescources,在裡面建立檔案phone.properties myphone是後面get...

《 Python 機器學習專題手冊》筆記 3

import numpy as np from sklearn import preprocessing data np.array 3,1.5,2,5.4 0,4,0.3,2.1 1,3.3,1.9,4.3 去除均值 data standardized preprocessing.scale da...