using System; using System.Threading.Tasks; using Castle.DynamicProxy; using FreeSql; using Admin.Core.Common; using Admin.Core.Extensions; using Admin.Core.Model.Output; namespace Admin.Core.Aop { public class TransactionInterceptor : IInterceptor { private readonly IUnitOfWork _unitOfWork; public TransactionInterceptor(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public async void Intercept(IInvocation invocation) { var method = invocation.MethodInvocationTarget ?? invocation.Method; if (method.HasAttribute()) { try { _unitOfWork.Open(); invocation.Proceed(); if (method.IsAsync()) { if (invocation.Method.ReturnType == typeof(Task)) { await (Task)invocation.ReturnValue; } else { AopHelper.CallGenericMethod( invocation, res => { if (res == null) { return; } var responseOutput = res as IResponseOutput; if (responseOutput != null && !responseOutput.Success) { _unitOfWork.Rollback(); } }, ex => { _unitOfWork.Rollback(); }); } } else { if (invocation.Method.ReturnType != typeof(void)) { var responseOutput = invocation.ReturnValue as Task; if (responseOutput != null && !responseOutput.Result.Success) { _unitOfWork.Rollback(); } } } _unitOfWork.Commit(); } catch (Exception) { _unitOfWork.Rollback(); throw; } finally { _unitOfWork.Close(); } } else { invocation.Proceed(); } } } }