前言
因為公司項目都是基於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
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。