Implement fully async interceptors.

pull/969/head
Halil ibrahim Kalkan 7 years ago
parent 1da13a0a68
commit 14df704c32

@ -35,7 +35,7 @@ namespace Volo.Abp.Authorization
return;
}
AsyncHelper.RunSync(() => AuthorizeAsync(invocation));
await AuthorizeAsync(invocation);
await invocation.ProceedAsync();
}

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
@ -8,6 +9,20 @@ namespace Volo.Abp.Castle.DynamicProxy
public class CastleAbpInterceptorAdapter<TInterceptor> : IInterceptor
where TInterceptor : IAbpInterceptor
{
private static readonly MethodInfo MethodExecuteWithoutReturnValueAsync =
typeof(CastleAbpInterceptorAdapter<TInterceptor>)
.GetMethod(
nameof(ExecuteWithoutReturnValueAsync),
BindingFlags.NonPublic | BindingFlags.Instance
);
private static readonly MethodInfo MethodExecuteWithReturnValueAsync =
typeof(CastleAbpInterceptorAdapter<TInterceptor>)
.GetMethod(
nameof(ExecuteWithReturnValueAsync),
BindingFlags.NonPublic | BindingFlags.Instance
);
private readonly TInterceptor _abpInterceptor;
public CastleAbpInterceptorAdapter(TInterceptor abpInterceptor)
@ -17,39 +32,58 @@ namespace Volo.Abp.Castle.DynamicProxy
public void Intercept(IInvocation invocation)
{
var proceedInfo = invocation.CaptureProceedInfo();
var method = invocation.MethodInvocationTarget ?? invocation.Method;
if (method.IsAsync())
{
InterceptAsyncMethod(invocation);
InterceptAsyncMethod(invocation, proceedInfo);
}
else
{
InterceptSyncMethod(invocation);
InterceptSyncMethod(invocation, proceedInfo);
}
}
private void InterceptAsyncMethod(IInvocation invocation)
private void InterceptSyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
_abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation, proceedInfo));
}
private void InterceptAsyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
if (invocation.Method.ReturnType == typeof(Task))
{
invocation.ReturnValue = _abpInterceptor.InterceptAsync(new CastleAbpMethodInvocationAdapter(invocation));
invocation.ReturnValue = MethodExecuteWithoutReturnValueAsync
.Invoke(this, new object[] { invocation, proceedInfo });
}
else
{
var interceptResult = _abpInterceptor.InterceptAsync(new CastleAbpMethodInvocationAdapter(invocation));
var actualReturnValue = invocation.ReturnValue;
invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult(
invocation.Method.ReturnType.GenericTypeArguments[0],
() => actualReturnValue,
() => interceptResult
);
invocation.ReturnValue = MethodExecuteWithReturnValueAsync
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] {invocation, proceedInfo});
}
}
private void InterceptSyncMethod(IInvocation invocation)
private async Task ExecuteWithoutReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
_abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation));
await Task.Yield();
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
);
}
private async Task<T> ExecuteWithReturnValueAsync<T>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
await Task.Yield();
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
);
return await (Task<T>)invocation.ReturnValue;
}
}
}

@ -32,10 +32,10 @@ namespace Volo.Abp.Castle.DynamicProxy
protected IInvocation Invocation { get; }
protected IInvocationProceedInfo ProceedInfo { get; }
public CastleAbpMethodInvocationAdapter(IInvocation invocation)
public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
Invocation = invocation;
ProceedInfo = invocation.CaptureProceedInfo();
ProceedInfo = proceedInfo;
_lazyArgumentsDictionary = new Lazy<IReadOnlyDictionary<string, object>>(GetArgumentsDictionary);
}
@ -53,7 +53,9 @@ namespace Volo.Abp.Castle.DynamicProxy
public Task ProceedAsync()
{
ProceedInfo.Invoke();
_actualReturnValue = Invocation.ReturnValue;
return Invocation.Method.IsAsync()
? (Task)_actualReturnValue
: Task.FromResult(_actualReturnValue);

@ -14,7 +14,7 @@ namespace Volo.Abp.DynamicProxy
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
//await Task.Delay(5); CAN NOT USE await before method execution! This is a restriction of Castle DynamicProxy
await Task.Delay(5);
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_InterceptAsync_BeforeInvocation");
await invocation.ProceedAsync();
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_InterceptAsync_AfterInvocation");

Loading…
Cancel
Save