以下是实现了Castle Dynamic Proxy库的IInterceptor
接口自定义类型中的Intercept
方法代码。这段代码取自一个基于面向切面编程(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;
}
}
我们发现在常规方法调用中,这个功能按预期工作,但是在使用C#5.0的async / await
关键字的async
方法中并不起作用。我相信我也理解了其中的原因。
为了让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...");
这仅适用于返回Task
或Task<>
而不是void
的async
方法,但我对此很满意。
在Intercept
方法中需要做哪些更改,以使awaiter
返回到那里而不是原始调用者?
ContinueWith
。是的,我希望拦截器继续记录返回值和任何异常。 - Hari Pachuveetil