98 lines
3.1 KiB
C#
98 lines
3.1 KiB
C#
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<TResult> InterceptAsync<TResult>(Task<TResult> 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<TResult> InterceptAsync<TResult>(ValueTask<TResult> 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;
|
|
}
|
|
}
|
|
}
|