(譯)乙個通用快速的反射方法呼叫

2022-01-12 20:18:58 字數 2383 閱讀 1701

原文:

介紹有時,我們會碰見需要動態呼叫物件方法的場景,而這個方法只有在執行的時候才能得知。通常的,會使用方法的反射呼叫,但是這通常會導致程式速度變慢。這篇文章將介紹一種高效替代方案

----

動態方法呼叫。

背景環境

當我讀到文章《

fast dynamic property accessors

》時,我想到我專案中在迴圈中運用了大量方法的反射呼叫,然而這樣呼叫是毫無效率的。

dynamicmethod

提醒我是否可在方法呼叫前使用

system.reflection.emit

生成dynamicmethod

繫結到指定的方法,這樣或許能提高程式效能。

**首先,使用反射找到將要呼叫的方法成員:

methodinfo methodinfo = typeof(person).getmethod("say");
然後,建立動態方法並且返**用該動態方法的委託:

fastinvokehandler fastinvoker = getmethodinvoker(methodinfo);

fastinvoker(new person(), new object);

代替之前方法的反射呼叫:

methodinfo.invoke(new person(), new object);
實現首先,我們需要為動態方法定義乙個適當的委託:

public delegate object fastinvokehandler(object target, object paramters);

為了不改變之前方法的反射呼叫模式,所以我們定義的委託接收引數和返回值類似

methodinfo.invoke()

。下面貼出

dynamicmethod

生成**:

public static fastinvokehandler getmethodinvoker(methodinfo methodinfo)

, methodinfo.declaringtype.module);

ilgenerator il = dynamicmethod.getilgenerator();

parameterinfo ps = methodinfo.getparameters();

type paramtypes = new type[ps.length];

for (int i = 0; i < paramtypes.length; i++)

localbuilder locals = new localbuilder[paramtypes.length];

for (int i = 0; i < paramtypes.length; i++)

for (int i = 0; i < paramtypes.length; i++)

il.emit(opcodes.ldarg_0);

for (int i = 0; i < paramtypes.length; i++)

il.emitcall(opcodes.call, methodinfo, null);

if (methodinfo.returntype == typeof(void))

il.emit(opcodes.ldnull);

else

emitboxifneeded(il, methodinfo.returntype);

il.emit(opcodes.ret);

fastinvokehandler invoder =

(fastinvokehandler)dynamicmethod.createdelegate(typeof(fastinvokehandler));

return invoder;

}

總結好了,我想這個通用方法可以代替大多數方法的反射同時會獲得大約

50倍的效率提高,歡迎反饋任何改善的建議。

另外值得注意的優勢(感謝

maxguernsey

的提醒):如果你呼叫的方法內部丟擲異常,

fastinovker

會丟擲具體錯誤資訊,然而

method.invoke

僅僅只會丟擲「呼叫目標發生異常

(targetinvocationexception)

」。整理了一篇文章對該篇進行補充及擴充套件,歡迎檢視《(譯)乙個通用快速的反射方法呼叫》續篇》

luyan

《(9)程式集的載入和反射》

通過反射機制呼叫乙個物件的方法

呼叫物件的方法的4要素 1.物件 2.方法名 3.引數 4.返回值 1.不使用反射機制呼叫方法 userservice userservice new userservice 建立物件 boolean loginresult userservice.login admin 123456 呼叫方法 s...

乙個通用分頁查詢方法

為了簡化開發人員的 想寫乙個通用的分頁查詢方法,為了提交效率,其中有一段是分解hql語句,組成查詢總數的hql語句,實現如下 public paginationsupport findpagebyquery final string hsql,final object values,final in...

呼叫乙個按鈕的Click事件(利用反射)

做了幾次。每次都忘記。所以記錄下來。測試環境如下 csharp view plain copy 建立乙個函式 private void callonclick button btn 呼叫例子。呼叫button1的onclick callonclick button1 呼叫button5的onclic...