ABP是“ASP.NET Boilerplate Project”的简称。
ABP的官方网站:
ABP在Github上的开源项目:https://github.com/aspnetboilerplate
ABP其他学习博客推荐及介绍:
ABP中Unit of Work概念及使用
如果这是你首次接触ABP框架或ABP的Unit of Work,推荐先看看 ABP使用及框架解析系列-[Unit of Work part.1-概念及使用]
框架实现 温馨提示
1.ABP的Unit of Work相关代码路径为:/Abp/Domain/Uow
2.框架实现中,代码不会贴全部的,但是会说明代码在项目中的位置,并且为了更加直观和缩短篇幅,对代码更细致的注释,直接在代码中,不要忘记看代码注释哈,。
3.博客中的代码,有一些方法是可以点击的!
动态代理/拦截器/AOP
上面讲到Unit of Work有两个默认实现,领域服务和仓储库的每个方法默认就是一个工作单元,这个是如何实现的呢?在方法上添加一个UnitOfWork特性也就让该方法为一个工作单元,这又是如何实现的呢?上面的标题已然暴露了答案——动态代理
在ABP中,使用了Castle的DynamicProxy进行动态代理,在组件注册是进行拦截器的注入,具体代码如下:
UnitOfWorkRegistrar { Initialize(IIocManager iocManager) {//该方法会在应用程序启动的时候调用,进行事件注册 iocManager.IocContainer.Kernel.ComponentRegistered += ComponentRegistered; } ComponentRegistered(string key, IHandler handler) { if (UnitOfWorkHelper.(handler.ComponentModel.Implementation)) {//判断类型是否实现了IRepository或IApplicationService,如果是,则为该类型注册拦截器(UnitOfWorkInterceptor) handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor))); } else if (handler.ComponentModel.Implementation.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(UnitOfWorkHelper.)) {//或者类型中任何一个方法上应用了UnitOfWorkAttribute,同样为类型注册拦截器(UnitOfWorkInterceptor) handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor))); } } }
IsConventionalUowClass(Type type) { return typeof(IRepository).IsAssignableFrom(type) || typeof(IApplicationService).IsAssignableFrom(type); }
HasUnitOfWorkAttribute(MemberInfo methodInfo) { return methodInfo.IsDefined(typeof(UnitOfWorkAttribute), true); }
拦截器UnitOfWorkInterceptor实现了IInterceptor接口,在调用注册了拦截器的类的方法时,会被拦截下来,而去执行IInterceptor的Intercept方法,下面是Intercept方法的代码实现:
public void Intercept(IInvocation invocation) { if (_unitOfWorkManager.Current != null) {//如果当前已经在工作单元中,则直接执行被拦截类的方法 invocation.Proceed(); return; } unitOfWorkAttr = UnitOfWorkAttribute.(invocation.MethodInvocationTarget); if (unitOfWorkAttr == null || unitOfWorkAttr.IsDisabled) {//如果当前方法上没有UnitOfWorkAttribute或者是设置为Disabled,则直接调用被拦截类的方法 invocation.Proceed(); return; } //走到这里就表示是需要将这个方法作为工作单元了,详情点击查看 (invocation, unitOfWorkAttr.CreateOptions()); }
internal static UnitOfWorkAttribute GetUnitOfWorkAttributeOrNull(MemberInfo methodInfo) { attrs = methodInfo.GetCustomAttributes(typeof(UnitOfWorkAttribute), false); if (attrs.Length > 0) { return (UnitOfWorkAttribute)attrs[0]; } if (UnitOfWorkHelper.IsConventionalUowClass(methodInfo.DeclaringType)) { UnitOfWorkAttribute(); } return null; }
private void PerformUow(IInvocation invocation, UnitOfWorkOptions options) { if (AsyncHelper.IsAsyncMethod(invocation.Method)) {//被拦截的方法为异步方法 (invocation, options); } else {//被拦截的方法为同步方法 (invocation, options); } }
private void PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options) { (var uow = _unitOfWorkManager.Begin(options)) { invocation.Proceed(); uow.Complete(); } }
private void PerformAsyncUow(IInvocation invocation, UnitOfWorkOptions options) { uow = _unitOfWorkManager.Begin(options); invocation.Proceed(); if (invocation.Method.ReturnType == typeof(Task)) {//如果是无返回值的异步任务 invocation.ReturnValue = InternalAsyncHelper.( (Task)invocation.ReturnValue, async () => await uow.CompleteAsync(), exception => uow.Dispose() ); } {//如果是有返回值的异步任务 invocation.ReturnValue = InternalAsyncHelper.( invocation.Method.ReturnType.GenericTypeArguments[0], invocation.ReturnValue, async () => await uow.CompleteAsync(), (exception) => uow.Dispose() ); } }