#80: Created Unit Of Work Interceptor.

pull/81/head
Halil İbrahim Kalkan 9 years ago
parent 7998045a14
commit 0292287fe3

@ -3,8 +3,8 @@ using System.Threading.Tasks;
using AbpDesk.Tickets.Dtos;
using Volo.Abp.Application.Services.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.Linq.Extensions;
using Volo.Abp.Uow;
using Volo.ExtensionMethods;
namespace AbpDesk.Tickets
@ -12,33 +12,32 @@ namespace AbpDesk.Tickets
public class TicketAppService : ITicketAppService
{
private readonly IQueryableRepository<Ticket, int> _ticketRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IAsyncQueryableExecuter _asyncQueryableExecuter;
public TicketAppService(
IQueryableRepository<Ticket, int> ticketRepository,
IUnitOfWorkManager unitOfWorkManager
IAsyncQueryableExecuter asyncQueryableExecuter
)
{
_ticketRepository = ticketRepository;
_unitOfWorkManager = unitOfWorkManager;
_asyncQueryableExecuter = asyncQueryableExecuter;
}
public async Task<ListResultDto<TicketDto>> GetAll(GetAllTicketsInput input)
{
//Use conventional unit of work for application services when it's available!
using (var unitOfWork = _unitOfWorkManager.Begin())
{
var tickets = _ticketRepository
.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
t => t.Title.Contains(input.Filter) || t.Body.Contains(input.Filter)
).Select(t => new TicketDto { Id = t.Id, Title = t.Title, Body = t.Body })
.ToList();
var tickets = await _asyncQueryableExecuter.ToListAsync(_ticketRepository
.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
t => t.Title.Contains(input.Filter) || t.Body.Contains(input.Filter)
)
.Select(t => new TicketDto
{
Id = t.Id,
Title = t.Title,
Body = t.Body
}));
await unitOfWork.CompleteAsync();
return new ListResultDto<TicketDto>(tickets);
}
return new ListResultDto<TicketDto>(tickets);
}
}
}

@ -15,7 +15,7 @@ namespace Volo.Abp.Threading
/// Checks if given method is an async method.
/// </summary>
/// <param name="method">A method to check</param>
public static bool IsAsyncMethod([NotNull] this MethodInfo method)
public static bool IsAsync([NotNull] this MethodInfo method)
{
return method.ReturnType == typeof(Task) ||
(method.ReturnType.GetTypeInfo().IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>));

@ -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 });
}
}
}

@ -4,7 +4,7 @@ using System.Threading.Tasks;
namespace Volo.Abp.Uow
{
//Find a better naming :(
//TODO: Find a better naming :(
public interface IBasicUnitOfWork : IDisposable
{
event EventHandler Completed;

@ -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()
);
}
}
}
}

@ -26,17 +26,17 @@ namespace Volo.Abp.Threading
GetType().GetMethod(
"MyTaskWithoutReturnValueAsync",
BindingFlags.NonPublic | BindingFlags.Static
).IsAsyncMethod().ShouldBe(true);
).IsAsync().ShouldBe(true);
GetType().GetMethod(
"MyTaskWithReturnValueAsync",
BindingFlags.NonPublic | BindingFlags.Static
).IsAsyncMethod().ShouldBe(true);
).IsAsync().ShouldBe(true);
GetType().GetMethod(
"MyTaskWithReturnValue2",
BindingFlags.NonPublic | BindingFlags.Instance
).IsAsyncMethod().ShouldBe(false);
).IsAsync().ShouldBe(false);
}
private static async Task MyTaskWithoutReturnValueAsync()

Loading…
Cancel
Save