using Castle.DynamicProxy; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace IRaCIS.Core.Application.AOP { 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); } } private bool CheckMethodReturnTypeIsTaskType(MethodInfo method) { var methodReturnType = method.ReturnType; if (methodReturnType.IsGenericType) { if (methodReturnType.GetGenericTypeDefinition() == typeof(Task<>) || methodReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>)) return true; } else { if (methodReturnType == typeof(Task) || methodReturnType == typeof(ValueTask)) return true; } return false; } private bool IsAsyncMethod(MethodInfo method) { bool isDefAsync = Attribute.IsDefined(method, typeof(AsyncStateMachineAttribute), false); bool isTaskType = CheckMethodReturnTypeIsTaskType(method); bool isAsync = isDefAsync && isTaskType; return isAsync; } protected object ProceedAsyncResult { get; set; } private async Task InterceptAsync(Task task, IInvocation invocation) { await task.ConfigureAwait(false); await AfterProceedAsync(invocation, false); } private async Task InterceptAsync(Task task, IInvocation invocation) { ProceedAsyncResult = await task.ConfigureAwait(false); await AfterProceedAsync(invocation, true); return (TResult)ProceedAsyncResult; } private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation) { await task.ConfigureAwait(false); await AfterProceedAsync(invocation, false); } private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation) { ProceedAsyncResult = await task.ConfigureAwait(false); 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; } } }