.net core autofac asyncinterceptor 非同步攔截器幫助包
autofac使用攔截器實現AOP,是基於Castle.Core的.然而Castle.Core並未提供原生非同步支援.所以需要使用幫助類實現,這在autofac官方文檔的已知問題中有詳細說明:
//autofaccn.readthedocs.io/en/latest/advanced/interceptors.html#asynchronous-method-interception
對於該問題的討論,最早出現於stackoverflow://stackoverflow.com/questions/28099669/intercept-async-method-that-returns-generic-task-via-dynamicproxy
James Skimming基於其中的一個答案,研發了一個幫助包即: Castle.Core.AsyncInterceptor
我之前也一直使用的是該方案,不過thepirat000隨後提出了一個使用dynamic的更加簡化的實現方法://stackoverflow.com/a/39784559/7726468
我對其進行了一些封裝,實現了一個新的幫助包,大家可以嘗試一下,項目地址在://github.com/wswind/lightwind
使用時,你可以通過nuget安裝Lightwind.Asyncinterceptor
也可以直接拷貝AsyncInterceptorBase.cs放入你的項目中.樣例程式碼可點擊這裡查看
其中的核心程式碼是封裝實現一個支援非同步處理的Interceptor,讓開發者僅需關心實現所攔截的方法,在執行前後該添加什麼處理邏輯.
核心源碼如下:
//inspired by : //stackoverflow.com/a/39784559/7726468
public abstract class AsyncInterceptorBase : IInterceptor
{
public AsyncInterceptorBase()
{
}
public void Intercept(IInvocation invocation)
{
BeforeProceed(invocation);
invocation.Proceed();
if (IsAsyncMethod(invocation.MethodInvocationTarget))
{
invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation);
}
else
{
AfterProceedSync(invocation);
}
}
protected bool IsAsyncMethod(MethodInfo method)
{
var attr = method.GetCustomAttributes<AsyncStateMachineAttribute>(true);
bool isAsync = (attr != null) && typeof(Task).IsAssignableFrom(method.ReturnType);
return isAsync;
}
private async Task InterceptAsync(Task task, IInvocation invocation)
{
await task.ConfigureAwait(false);
await AfterProceedAsync(invocation, false);
}
protected object ProceedAsynResult { get; set; }
private async Task<TResult> InterceptAsync<TResult>(Task<TResult> task, IInvocation invocation)
{
TResult result = await task.ConfigureAwait(false);
ProceedAsynResult = result;
await AfterProceedAsync(invocation,true);
return (TResult)ProceedAsynResult;
}
protected virtual void BeforeProceed(IInvocation invocation) {}
protected virtual void AfterProceedSync(IInvocation invocation) {}
protected virtual Task AfterProceedAsync(IInvocation invocation,bool hasAsynResult)
{
return Task.CompletedTask;
}
}
非同步攔截器的執行流程如下:
在所攔截的方法執行前,首先執行BeforeProceed,方法執行後,如果為同步方法,則後續執行AfterProceedSync
如果為非同步方法,則await方法使其真正執行後,調用AfterProceedAsync.通過hasAsynResult可判斷是否有返回值.
如果有返回值也可通過ProceedAsynResult讀取或修改所攔截方法的最終返回值.
對於此問題的其他攔截器實現方法的程式碼樣例,可參照程式碼://github.com/wswind/Learn-AOP/tree/master/AutofacAsyncInterceptor-More