基於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

  來源:簡書
  著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM