原文:
介紹有時,我們會碰見需要動態呼叫物件方法的場景,而這個方法只有在執行的時候才能得知。通常的,會使用方法的反射呼叫,但是這通常會導致程式速度變慢。這篇文章將介紹一種高效替代方案
----
動態方法呼叫。
背景環境
當我讀到文章《
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...