public static void EmitLock(this ILProcessor il, Action loadSyncRoot, Action block)
{
var lockTaken = new VariableDefinition("$lockTaken", il.Body.Method.Module.Import(typeof(bool)));
il.Body.Variables.Add(lockTaken);
var syncRoot = new VariableDefinition("$root", il.Body.Method.Module.Import(typeof(object)));
il.Body.Variables.Add(syncRoot);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc, lockTaken);
il.EmitTryFinally(() =>
{
loadSyncRoot();
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Stloc, syncRoot);
il.Emit(OpCodes.Ldloca, lockTaken);
il.Emit(OpCodes.Call, il.Body.Method.Module.Import(_monitorEnter));
block();
}, () =>
{
il.Emit(OpCodes.Ldloc, lockTaken);
using (il.BranchIfFalse())
{
il.Emit(OpCodes.Ldloc, syncRoot);
il.Emit(OpCodes.Call, il.Body.Method.Module.Import(_monitorExit));
}
});
}