這個簡單的代碼工作正常,並允許在每個Update/LateUpdate/FixedUpdate
函數週圍添加一個BeginSample/EndSample
調用。但是,它不考慮提前退貨指示,例如由於某種情況。你知道如何編寫一個類似的函數來考慮早期返回,以便在任何情況下執行EndSample調用?使用塞西爾插入功能的開始/結束塊
請注意,我不是塞西爾專家,我現在只是在學習。在我看來,塞西爾在呼叫InsertBefore
和類似功能後自動更新返回的操作。所以如果一個BR
操作碼先前跳轉到一個特定的指令地址,那麼在插入之後該地址將被更新以便跳轉到原始指令。這在大多數情況下都可以,但在我的情況下,這意味着if
語句會跳過上一次插入的操作,因爲BR
操作仍然會直接指向最終的Ret
指令。請注意,Update
,LateUpdate
和FixedUpdate
都是無效功能。
foreach (var method in type.Methods)
{
if ((method.Name == "Update" || method.Name == "LateUpdate" || method.Name == "FixedUpdate") &&
method.HasParameters == false)
{
var beginMethod =
module.ImportReference(typeof (Profiler).GetMethod("BeginSample",
new[] {typeof (string)}));
var endMethod =
module.ImportReference(typeof (Profiler).GetMethod("EndSample",
BindingFlags.Static |
BindingFlags.Public));
Debug.Log(method.Name + " method found in class: " + type.Name);
var ilProcessor = method.Body.GetILProcessor();
var first = method.Body.Instructions[0];
ilProcessor.InsertBefore(first,
Instruction.Create(OpCodes.Ldstr,
type.FullName + "." + method.Name));
ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Call, beginMethod));
var lastRet = method.Body.Instructions[method.Body.Instructions.Count - 1];
ilProcessor.InsertBefore(lastRet, Instruction.Create(OpCodes.Call, endMethod));
changed = true;
}
}
作爲獎勵,如果你能向我解釋Emit
和Append
用相同的操作數新創建的指令之間的差異。是否在底層執行一個Emit
或做更多的事情?
快速評論之前,而一無所知約塞西爾:如果要保證的東西,無論總是會發生的內部控制流程,在它包裹了'試着......終於'塊將是明顯的事情要做,而不是追捕所有出口點。另一個顯而易見的方法是將原始函數重命名爲完全替換爲'begin()/ function()/ end()'的包裝器。最後但並非最不重要的一點是,您可以考慮使用分析器而不是顯然重新發明輪子。當然,不是說你真的不需要自己的車輪。 –