mirror of https://github.com/abpframework/abp.git
6 changed files with 265 additions and 24 deletions
@ -0,0 +1,181 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Threading |
|||
{ |
|||
internal static class InternalAsyncHelper |
|||
{ |
|||
public static async Task AwaitTaskWithFinally(Task actualReturnValue, Action<Exception> finalAction) |
|||
{ |
|||
Exception exception = null; |
|||
|
|||
try |
|||
{ |
|||
await actualReturnValue; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exception = ex; |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
finalAction(exception); |
|||
} |
|||
} |
|||
|
|||
public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) |
|||
{ |
|||
Exception exception = null; |
|||
|
|||
try |
|||
{ |
|||
await actualReturnValue; |
|||
await postAction(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exception = ex; |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
finalAction(exception); |
|||
} |
|||
} |
|||
|
|||
public static async Task AwaitTaskWithPreActionAndPostActionAndFinally(Func<Task> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null) |
|||
{ |
|||
Exception exception = null; |
|||
|
|||
try |
|||
{ |
|||
if (preAction != null) |
|||
{ |
|||
await preAction(); |
|||
} |
|||
|
|||
await actualReturnValue(); |
|||
|
|||
if (postAction != null) |
|||
{ |
|||
await postAction(); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exception = ex; |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
if (finalAction != null) |
|||
{ |
|||
finalAction(exception); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static async Task<T> AwaitTaskWithFinallyAndGetResult<T>(Task<T> actualReturnValue, Action<Exception> finalAction) |
|||
{ |
|||
Exception exception = null; |
|||
|
|||
try |
|||
{ |
|||
return await actualReturnValue; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exception = ex; |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
finalAction(exception); |
|||
} |
|||
} |
|||
|
|||
public static object CallAwaitTaskWithFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Action<Exception> finalAction) |
|||
{ |
|||
return typeof(InternalAsyncHelper) |
|||
.GetTypeInfo() |
|||
.GetMethod("AwaitTaskWithFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static) |
|||
.MakeGenericMethod(taskReturnType) |
|||
.Invoke(null, new object[] { actualReturnValue, finalAction }); |
|||
} |
|||
|
|||
public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) |
|||
{ |
|||
Exception exception = null; |
|||
|
|||
try |
|||
{ |
|||
var result = await actualReturnValue; |
|||
await postAction(); |
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exception = ex; |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
finalAction(exception); |
|||
} |
|||
} |
|||
|
|||
public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Func<Task> action, Action<Exception> finalAction) |
|||
{ |
|||
return typeof (InternalAsyncHelper) |
|||
.GetTypeInfo() |
|||
.GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static) |
|||
.MakeGenericMethod(taskReturnType) |
|||
.Invoke(null, new object[] { actualReturnValue, action, finalAction }); |
|||
} |
|||
|
|||
public static async Task<T> AwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult<T>(Func<Task<T>> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null) |
|||
{ |
|||
Exception exception = null; |
|||
|
|||
try |
|||
{ |
|||
if (preAction != null) |
|||
{ |
|||
await preAction(); |
|||
} |
|||
|
|||
var result = await actualReturnValue(); |
|||
|
|||
if (postAction != null) |
|||
{ |
|||
await postAction(); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
exception = ex; |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
if (finalAction != null) |
|||
{ |
|||
finalAction(exception); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static object CallAwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult(Type taskReturnType, Func<object> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null) |
|||
{ |
|||
return typeof(InternalAsyncHelper) |
|||
.GetTypeInfo() |
|||
.GetMethod("AwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static) |
|||
.MakeGenericMethod(taskReturnType) |
|||
.Invoke(null, new object[] { actualReturnValue, preAction, postAction, finalAction }); |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +1,74 @@ |
|||
using Volo.Abp.DynamicProxy; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DynamicProxy; |
|||
using Volo.Abp.Threading; |
|||
using Volo.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Uow |
|||
{ |
|||
public class UnitOfWorkInterceptor : IAbpInterceptor, ITransientDependency |
|||
{ |
|||
private readonly IUnitOfWorkManager _unitOfWorkManager; |
|||
|
|||
public UnitOfWorkInterceptor(IUnitOfWorkManager unitOfWorkManager) |
|||
{ |
|||
_unitOfWorkManager = unitOfWorkManager; |
|||
} |
|||
|
|||
|
|||
public void Intercept(IAbpMethodInvocation invocation) |
|||
{ |
|||
invocation.Proceed(); |
|||
//TODO: Check UOW attribute and other conditions!
|
|||
|
|||
if (invocation.Method.IsAsync()) |
|||
{ |
|||
PerformAsyncUow(invocation); |
|||
} |
|||
else |
|||
{ |
|||
PerformSyncUow(invocation); |
|||
} |
|||
} |
|||
|
|||
private void PerformSyncUow(IAbpMethodInvocation invocation) |
|||
{ |
|||
using (var uow = _unitOfWorkManager.Begin()) |
|||
{ |
|||
invocation.Proceed(); |
|||
uow.Complete(); |
|||
} |
|||
} |
|||
|
|||
private void PerformAsyncUow(IAbpMethodInvocation invocation) |
|||
{ |
|||
var uow = _unitOfWorkManager.Begin(); |
|||
|
|||
try |
|||
{ |
|||
invocation.Proceed(); |
|||
} |
|||
catch |
|||
{ |
|||
uow.Dispose(); |
|||
throw; |
|||
} |
|||
|
|||
if (invocation.Method.ReturnType == typeof(Task)) |
|||
{ |
|||
invocation.ReturnValue = InternalAsyncHelper.AwaitTaskWithPostActionAndFinally( |
|||
(Task)invocation.ReturnValue, |
|||
async () => await uow.CompleteAsync(), |
|||
exception => uow.Dispose() |
|||
); |
|||
} |
|||
else //Task<TResult>
|
|||
{ |
|||
invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult( |
|||
invocation.Method.ReturnType.GenericTypeArguments[0], |
|||
invocation.ReturnValue, |
|||
async () => await uow.CompleteAsync(), |
|||
exception => uow.Dispose() |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue