diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs index 7d5007da04..7c89bcbe11 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptor.cs @@ -35,7 +35,7 @@ namespace Volo.Abp.Authorization return; } - AsyncHelper.RunSync(() => AuthorizeAsync(invocation)); + await AuthorizeAsync(invocation); await invocation.ProceedAsync(); } diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs index 1b1b958ff1..edb52aff86 100644 --- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs +++ b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs @@ -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 : IInterceptor where TInterceptor : IAbpInterceptor { + private static readonly MethodInfo MethodExecuteWithoutReturnValueAsync = + typeof(CastleAbpInterceptorAdapter) + .GetMethod( + nameof(ExecuteWithoutReturnValueAsync), + BindingFlags.NonPublic | BindingFlags.Instance + ); + + private static readonly MethodInfo MethodExecuteWithReturnValueAsync = + typeof(CastleAbpInterceptorAdapter) + .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 ExecuteWithReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo) + { + await Task.Yield(); + + await _abpInterceptor.InterceptAsync( + new CastleAbpMethodInvocationAdapter(invocation, proceedInfo) + ); + + return await (Task)invocation.ReturnValue; } } } diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs index 5fd4270854..0963da406b 100644 --- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs +++ b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs @@ -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>(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); diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/SimpleAsyncInterceptor.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/SimpleAsyncInterceptor.cs index 10a072c3c7..f1f868700a 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/SimpleAsyncInterceptor.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/SimpleAsyncInterceptor.cs @@ -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");