Без сборки и перезаписи IL невозможно создать пользовательский атрибут, который изменяет код так, как вы его описываете.
Я предлагаю вместо этого использовать подход на основе делегатов, например, для функций с одним аргументом:
static Func<TArg,T> WrapAgainstReentry<TArg,T>(Func<TArg,T> code, Func<TArg,T> onReentry)
{
bool entered = false;
return x =>
{
if (entered)
return onReentry(x);
entered = true;
try
{
return code(x);
}
finally
{
entered = false;
}
};
}
Этот метод принимает функцию для переноса (при условии, что она соответствует Func - вы можете написать другие варианты или полностью универсальную версию с большими усилиями) и альтернативную функцию для вызова в случае повторного входа. (Альтернативная функция может выдать исключение или немедленно вернуться и т. Д.) Затем во всем коде, где вы обычно вызываете переданный метод, вместо этого вы вызываете делегат, возвращаемый WrapAgainstReentry ().