.net core autofac asyncinterceptor 異步攔截器幫助包


背景

autofac使用攔截器實現AOP,是基於Castle.Core的.然而Castle.Core並未提供原生異步支持.所以需要使用幫助類實現,這在autofac官方文檔的已知問題中有詳細說明
對於該問題的討論,最早出現於stackoverflow
James Skimming基於其中的一個答案,研發了一個幫助包即: Castle.Core.AsyncInterceptor
我之前也一直使用的是該方案,不過thepirat000隨后提出了一個使用dynamic的更加簡化的實現方法
我對該方法進行了一些封裝,實現了一個幫助包,大家可以嘗試一下。

項目地址:https://github.com/wswind/lightwind

使用

使用時,你可以通過nuget安裝Lightwind.Asyncinterceptor也可以直接拷貝AsyncInterceptorBase.cs放入你的項目中.樣例代碼可點擊這里查看
其核心代碼是封裝實現一個支持異步處理的Interceptor父類,讓開發者能夠繼承實現自己的攔截器。開發時,僅需關注所攔截的方法,在執行前后該添加什么處理邏輯.
異步攔截器的執行流程如下:
在所攔截的方法執行前,首先執行BeforeProceed,方法執行后,如果為同步方法,則后續執行AfterProceedSync
如果為異步方法,則await所攔截的方法使其真正執行后,調用AfterProceedAsync進行異步方法的后續處理。
對於異步執行且有返回值的情況,可通過hasAsynResult參數判斷是否有返回值,通過ProceedAsynResult屬性讀取或修改所攔截方法的最終返回值.
代碼的運行流程圖如下:

AsyncInterceptorBase.cs核心實現如下:

// Licence: MIT
// Author: Vicent Wang
// Email: ws_dev@163.com
// ProjectUrl: https://github.com/wswind/lightwind

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Castle.DynamicProxy;

namespace Lightwind.AsyncInterceptor
{
    //inspired by : https://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);
            }
        }

        //didn't support ValueTask yet
        protected virtual bool IsAsyncMethod(MethodInfo method)
        {
            bool isDefAsync = Attribute.IsDefined(method, typeof(AsyncStateMachineAttribute), false);
            bool isAsync = isDefAsync && 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 ProceedAsyncResult { get; set; }

        private async Task<TResult> InterceptAsync<TResult>(Task<TResult> task, IInvocation invocation)
        {
            TResult result = await task.ConfigureAwait(false);
            ProceedAsyncResult = result;
            await AfterProceedAsync(invocation, true);
            return (TResult)ProceedAsyncResult;
        }

        protected virtual void BeforeProceed(IInvocation invocation) { }

        protected virtual void AfterProceedSync(IInvocation invocation) { }

        protected virtual Task AfterProceedAsync(IInvocation invocation, bool hasAsynResult)
        {
            return Task.CompletedTask;
        }
    }
}

對於異步攔截器的其他實現方法,可參考此代碼樣例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM