修改异步返回结果,并且使用try...catch...finally Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) { Exception exception = null; { await actualReturnValue; await postAction(); } catch (Exception ex) { exception = ex; throw; } finally { finalAction(exception); } }
CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Func<Task> action, Action<Exception> finalAction) { (InternalAsyncHelper) .GetMethod(, BindingFlags.Public | BindingFlags.Static) .MakeGenericMethod(taskReturnType) .Invoke(null, new object[] { actualReturnValue, action, finalAction }); }
Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) { Exception exception = null; { var result = await actualReturnValue; await postAction(); return result; } catch (Exception ex) { exception = ex; throw; } finally { finalAction(exception); } }
总结来说,就是通过拦截器在执行方法的时候,先判断是否需要进行工作单元操作。如果需要,则在执行方法前开启工作单元,在执行方法后关闭工作单元。
在上面的代码中,我们可以看到,工作单元都是通过_unitOfWorkManager(IUnitOfWorkManager)这样一个对象进行的,下面我们就来解析这个类到底是如何进行单元控制的。
IUnitOfWorkManager、IUnitOfWorkCompleteHandle
public interface IUnitOfWorkManager { IActiveUnitOfWork Current { get; } IUnitOfWorkCompleteHandle Begin(); IUnitOfWorkCompleteHandle Begin(TransactionScopeOption scope); IUnitOfWorkCompleteHandle Begin(UnitOfWorkOptions options); }
ABP中,默认将UnitOfWorkManager作为IUnitOfWorkManager作为实现类,其实现中,Current直接取得ICurrentUnitOfWorkProvider对象的属性,后续解析ICurrentUnitOfWorkProvider。而IUnitOfWorkManager的三个Begin只是重载,最后都将调用第三个Begin的重载方法。下面是它的代码实现:
public IUnitOfWorkCompleteHandle Begin(UnitOfWorkOptions options) { //为未赋值的参数设置默认值 options.(_defaultOptions); if (options.Scope == TransactionScopeOption.Required && _currentUnitOfWorkProvider.Current != null) { InnerUnitOfWorkCompleteHandle(); } uow = _iocResolver.Resolve<IUnitOfWork>(); uow.Completed += (sender, args) => { _currentUnitOfWorkProvider.Current = null; }; uow.Failed += (sender, args) => { _currentUnitOfWorkProvider.Current = null; }; uow.Disposed += (sender, args) => { _iocResolver.Release(uow); }; uow.Begin(options); _currentUnitOfWorkProvider.Current = uow; return uow; }
public IActiveUnitOfWork Current { get { return _currentUnitOfWorkProvider.Current; } }
internal void FillDefaultsForNonProvidedOptions(IUnitOfWorkDefaultOptions defaultOptions) { if (!IsTransactional.HasValue) { IsTransactional = defaultOptions.IsTransactional; } if (!Scope.HasValue) { Scope = defaultOptions.Scope; } if (!Timeout.HasValue && defaultOptions.Timeout.HasValue) { Timeout = defaultOptions.Timeout.Value; } if (!IsolationLevel.HasValue && defaultOptions.IsolationLevel.HasValue) { IsolationLevel = defaultOptions.IsolationLevel.Value; } }
Begin方法最后返回的对象继承自IUnitOfWorkCompleteHandle,让我们看看IUnitOfWorkCompleteHandle的接口声明又是什么样的:
public interface IUnitOfWorkCompleteHandle : IDisposable { void Complete(); Task CompleteAsync(); }
总共也就两个方法,而且意思相同,都是用来完成当前工作单元的,一个同步一个异步。同时实现了IDisposable接口,结合IUnitOfWorkManager使用Begin的方式便可理解其含义(使用using)。