Below is the code from the Intercept
method on a custom type that implements IInterceptor
of the Castle Dynamic Proxy library. This snippet is from an AOP based logging proof-of-concept console app that is posted here.
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;
}
}
This is working as expected on regular method calls, but not when tried with async
methods (using the async/await
keywords from C# 5.0). And I believe, I understand the reasons behind this as well.
For the async/await
to work, the compiler adds the functional body of the method into a state machine behind the scenes and the control will return to the caller, as soon as the first awaitable
expression that cannot be completed synchronously, is encountered.
Also, we can interrogate the return type and figure out whether we are dealing with an async
method like this:
if (invocation.Method.ReturnType == typeof(Task) ||
(invocation.Method.ReturnType.IsGenericType &&
invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)))
Log.Info("Asynchronous method found...");
This works for only those async
methods that returns either Task
or Task<>
and not void
but I am fine with that.
What changes have to made within the Intercept
method so that the awaiter
would return to there rather than the original caller?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…