基于ABP扩展类似审计(IHasCreationTime)功能

 

前言

  因为公司项目都是基于abp这套框架来实现功能,最近项目在调整所以我们想自己实现Module-Zero相应的功能,毕竟Module-Zero 是收费的(你懂的)今天就是实现类似审计(IHasCreationTime等)自动添加创建人,创建时间功能(子帐号概念)

思路

  1. 首先想到的是重写abp关于仓储的新增方法,代码确实很多,自身又对abp的源码没有太多的研究,放弃

  2. 每次实例化实体的时候手动给所属帐号Id手动赋值,麻烦,放弃

  3. 参考abp关于IHasCreationTime审计功能自动添加创建用户Id的思路,在继承AbpDbContext(数据上下文)中类中重写AbpDbContext定义的ObjectStateManager_ObjectStateManagerChanged这个方法。然后再声明一个受保护的SetChildAcountProperties方法用户给自账号相应字段赋值。

问题

  1. 本来想直接在XXXXXXDbContext:AbpDbContext类中声明一个基于IAbpsession扩展的Abpsession属性的,结果发现还不能这样写,关于拓展abpsession的文章请看连接博客园【圣杰】的ABP入门系列(10)——扩展AbpSession,后面采用了其他方式进行获取相应的值,下面的代码中会说明。请教各位大神为何在XXXXXXDbContext不能像下面这样获取拓展之后的AbpSession值

    public new IAbpSessionExtensions AbpSession { get; set; } 

     

  2. 本身我们子帐号就是获取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         }
View Code
  • 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

  來源:简书
  著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted @ 2017-07-20 11:44  性感的小胡子  阅读(1750)  评论(1编辑  收藏  举报