前言
因为公司项目都是基于abp这套框架来实现功能,最近项目在调整所以我们想自己实现Module-Zero相应的功能,毕竟Module-Zero 是收费的(你懂的)今天就是实现类似审计(IHasCreationTime等)自动添加创建人,创建时间功能(子帐号概念)
思路
-
首先想到的是重写abp关于仓储的新增方法,代码确实很多,自身又对abp的源码没有太多的研究,放弃
-
每次实例化实体的时候手动给所属帐号Id手动赋值,麻烦,放弃
-
参考abp关于IHasCreationTime审计功能自动添加创建用户Id的思路,在继承AbpDbContext(数据上下文)中类中重写AbpDbContext定义的ObjectStateManager_ObjectStateManagerChanged这个方法。然后再声明一个受保护的SetChildAcountProperties方法用户给自账号相应字段赋值。
问题
-
本来想直接在XXXXXXDbContext:AbpDbContext类中声明一个基于IAbpsession扩展的Abpsession属性的,结果发现还不能这样写,关于拓展abpsession的文章请看连接博客园【圣杰】的ABP入门系列(10)——扩展AbpSession,后面采用了其他方式进行获取相应的值,下面的代码中会说明。请教各位大神为何在XXXXXXDbContext不能像下面这样获取拓展之后的AbpSession值
public new IAbpSessionExtensions AbpSession { get; set; }
- 本身我们子帐号就是获取abpsession的UserId,我就想能不能在获取了abpsession.UserId之后在数据上下文中使用Users.Find(AbpSession.UserId)方法来查找我需要的其他字段,发现可以但是引发了一个其他地方的问题代码如下,提示“未将对象设置到引用的错误”
_xxxxxxRepository.Insert(model);
实现
- 重写XXXXXXDbContext:AbpDbContext类中的ObjectStateManager_ObjectStateManagerChanged

1 protected override void ObjectStateManager_ObjectStateManagerChanged(object sender, CollectionChangeEventArgs e) 2 { 3 var contextAdapter = (IObjectContextAdapter)this; 4 if (e.Action != CollectionChangeAction.Add) 5 { 6 return; 7 } 8 9 var entry = contextAdapter.ObjectContext.ObjectStateManager.GetObjectStateEntry(e.Element); 10 switch (entry.State) 11 { 12 case EntityState.Added: 13 CheckAndSetId(entry.Entity); 14 CheckAndSetMustHaveTenantIdProperty(entry.Entity); 15 SetCreationAuditProperties(entry.Entity, GetAuditUserId()); 16 SetChildAcountProperties(entry.Entity); 17 break; 18 } 19 }
- SetChildAcountProperties方法如下:
/// <summary> /// 设置子帐号属性字段值 /// </summary> /// <param name="entityAsObj">实体对象设置成Obj</param> protected void SetChildAcountProperties(object entityAsObj) { var entityWithChildAccount = entityAsObj as IChildAccount; if (entityWithChildAccount == null) { return; } var entity = entityAsObj.As<IChildAccount>(); if (!string.IsNullOrWhiteSpace(GetClaimValue(ClaimTypes.NameIdentifier))) entity.BelongUserId = Convert.ToInt64(GetClaimValue(ClaimTypes.NameIdentifier)); if (!string.IsNullOrWhiteSpace(GetClaimValue(ClaimTypeExtensions.LayerCode))) entity.UserLayerCode = GetClaimValue(ClaimTypeExtensions.LayerCode); }
- 其中GetClaimValue方法就是没有在拓展abpsession属性中拿取到才使用的折中的办法,其实按照博客园大神说的abpsession拓展的核心还是从用户申明(Claims)中获取,代码如下:
/// <summary> /// 获取申明值 /// </summary> /// <returns></returns> protected string GetClaimValue(string claimType) { var claimsPrincipal = DefaultPrincipalAccessor.Instance.Principal; var claim = claimsPrincipal?.Claims.FirstOrDefault(c => c.Type == claimType); return string.IsNullOrEmpty(claim?.Value) ? null : claim.Value; }
- 至此已经完成了代码的功能,有图有真相
总结
文章中是自己的理解,仅供参考abp路还很长,需要继续努力学习,很多很好的思想,思路都需要借鉴!!!
延伸
还有一个“”姿势”点就是可以做数据筛选,博客园中有很多关于自定义拓展abpDataFilter的文章都可以关注一下,期待下一篇更新吧
参考
文章中关于abpsession拓展的思路是来自:
作者:圣杰
链接:http://www.jianshu.com/p/930c10287e2a
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。