Ниже приведен код из метода Intercept
для настраиваемого типа, который реализует IInterceptor
библиотеки Castle Dynamic Proxy. Этот фрагмент представлен из AOP, основанного на протоколе верификации консольного приложения, которое опубликовано .
public void Intercept(IInvocation invocation)
{
if (Log.IsDebugEnabled) Log.Debug(CreateInvocationLogString("Called", invocation));
try
{
invocation.Proceed();
if (Log.IsDebugEnabled)
if (invocation.Method.ReturnType != typeof(void))
Log.Debug("Returning with: " + invocation.ReturnValue);
}
catch (Exception ex)
{
if (Log.IsErrorEnabled) Log.Error(CreateInvocationLogString("ERROR", invocation), ex);
throw;
}
}
Это работает как ожидалось при регулярных вызовах методов, но не при использовании методов async
(используя ключевые слова async/await
из С# 5.0). И я верю, я понимаю причины этого.
Для работы async/await
компилятор добавляет функциональное тело метода в конечный автомат за кулисами, и элемент управления вернется к вызывающему, как только первое выражение awaitable
, которое невозможно выполнить синхронно, встречается.
Кроме того, мы можем опросить тип возвращаемого значения и выяснить, имеем ли мы дело с методом async
следующим образом:
if (invocation.Method.ReturnType == typeof(Task) ||
(invocation.Method.ReturnType.IsGenericType &&
invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)))
Log.Info("Asynchronous method found...");
Это работает только для тех методов async
, которые возвращают либо Task
, либо Task<>
, а не void
, но я в порядке с этим.
Какие изменения необходимо внести в метод Intercept
, чтобы awaiter
вернулся туда, а не исходный вызывающий?