.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

Tags: