<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      實現領域驅動設計 - 使用ABP框架 - 應用程序服務

      應用程序服務

      應用程序服務是一種無狀態的服務,它實現應用程序的用例。應用程序服務通常獲取和返回dto。它由表示層使用。它使用并協調領域對象(實體、存儲庫等)來實現用例

      應用程序服務的常見原則如下:

      • 實現特定于當前用例的應用程序邏輯。不要在應用程序服務內部實現核心領域邏輯。我們將回到應用程序領域邏輯之間的差異
      • 永遠不要為應用程序服務方法獲取或返回實體。這打破了領域層的封裝。總是獲取和返回dto

      示例:分配問題給用戶

      public class IssueAppService : ApplicationService, IIssueAppService
      {
          //省略了Repository和DomainService的依賴注入
          public async Task AssignAsync(IssueAssignDto input)
          {
              var issue = await _issueRepository.GetAsync(input.IssueId);
              var user = await _userRepository.GetAsync(input.UserId);
      
              await _issueManager.AssignToAsync(issue, user);
              await _issueRepository.UpdateAsync(issue);
          }
      }
      

      應用程序服務方法通常有三個步驟,在這里實現了

      1. 從數據庫中獲取相關的領域對象來實現用例
      2. 使用領域對象(領域服務、實體等)執行實際操作
      3. 更新已更改的實體到數據庫中

      如果你正在使用EF Core,上面的更新是不必要的,因為它有一個更改跟蹤系統。如果你想利用這個EF Core特性,請參閱 關于數據庫無關心原則的討論部分

      本例中的 IssueAssignDto 是一個簡單的DTO類:

      public class IssueAssignDto
      {
          public Guid IssueId { get; set; }
          public Guid UserId { get; set; }
      }
      

      數據傳輸對象(DTO)

      DTO是一個簡單的對象,用于在應用程序層和表示層之間傳輸狀態(數據)。因此,應用程序服務方法獲取和返回dto

      通用DTO原則和最佳實踐:

      • 就其本質而言,DTO應該是可序列化的。因為,大多數時候它是通過網絡傳輸的。因此,它應該有一個無參數(空)構造函數。
      • 不應該包含業務邏輯。
      • 永遠不要繼承或引用實體。

      輸入dto(傳遞給應用程序服務方法的dto)與輸出dto(從應用程序服務方法返回的dto)具有不同的性質。所以,他們會被區別對待

      輸入DTO最佳實踐

      不要為輸入dto定義未使用的屬性

      只定義用例所需的屬性! 否則,客戶端在使用Application Service方法時會感到困惑。您當然可以定義可選屬性,但是當客戶端提供它們時,它們應該影響用例的工作方式

      首先,這條規則似乎沒有必要。誰會為方法定義未使用的參數(輸入DTO屬性)?但是,這種情況會發生,尤其是當您試圖重用輸入dto時。

      不要復用輸入dto

      為每個用例定義專門的輸入DTO(應用程序服務方法)。 否則,某些屬性在某些情況下不使用,這違反了上面定義的規則:不要為輸入dto定義未使用的屬性

      有時,為兩個用例重用同一個DTO類似乎很有吸引力,因為它們幾乎是相同的。即使他們現在是一樣的,他們可能會變成不同的時候,你會遇到相同的問題。代碼復制是比耦合用例更好的實踐

      重用輸入dto的另一種方法是相互繼承dto。雖然這在一些罕見的情況下是有用的,但大多數情況下它會使你達到相同的目的

      示例:用戶應用服務

      public interface IUserAppService : IApplicationService
      {
          Task CreateAsync(UserDto input);
          Task UpdateAsync(UserDto input);
          Task ChangePasswordAsync(UserDto input);
      }
      

      IUserAppService 在所有方法(用例)中使用 UserDto 作為輸入DTO。UserDto的定義如下:

      public class UserDto
      {
          public Guid UserId { get; set; }
          public string UserName { get; set; }
          public string Email { get; set; }
          public string Password { get; set; }
          public DateTime CreationTime { get; set; }
      }
      

      對于這個示例:

      • Id 在創建中不使用,因為服務器會在創建用戶時自動生成它
      • Password 沒有在更新中使用,因為我們有另一個更新密碼的方法
      • CreationTime 從不被使用,因為我們不能允許客戶端發送創建時間。它應該在服務器中設置

      真正的實現可以是這樣的:

      public interface IUserAppService : IApplicationService
      {
          Task CreateAsync(UserCreationDto input);
          Task UpdateAsync(UserUpdateDto input);
          Task ChangePasswordAsync(UserChangePasswordDto input);
      }
      

      盡管編寫了更多的代碼,但這是一種更易于維護的方法

      例外情況:該規則可能有一些例外:如果您總是希望并行開發兩個方法,它們可能共享相同的輸入DTO(通過繼承或直接重用)。例如,如果您有一個具有一些過濾器的報告頁面,并且您有多個Application Service方法(如屏幕報告、excel報告和csv報告方法)使用相同的過濾器但返回不同的結果,您可能希望重用相同的過濾器輸入DTO來耦合這些用例。因為,在本例中,無論何時更改過濾器,您都必須對所有方法進行必要的更改,以擁有一致的報告系統。

      輸入DTO驗證邏輯

      • 只在DTO內部實現形式驗證。使用數據注釋驗證屬性或實現IValidatableObject 進行形式驗證。
      • 不要執行領域驗證。例如,不要嘗試檢查dto中的唯一用戶名約束

      示例:使用數據注釋屬性

      public class UserCreationDto
      {
          [Required]
          [StringLength(UserConsts.MaxUserNameLength)]
          public string UserName { get; set; }
      
          [Required]
          [EmailAddress]
          [StringLength(UserConsts.MaxEmailLength)]
          public string Email { get; set; }
      
          [Required]
          [StringLength(UserConsts.MaxPasswordLength, MinimumLength = UserConsts.MaxMinPasswordLength)]
          public string Password { get; set; }
      }
      

      ABP框架自動驗證輸入的dto,拋出AbpValidationException,并在無效輸入的情況下向客戶端返回HTTP狀態400

      一些開發人員認為最好將驗證規則和DTO類分開。我們認為聲明式(數據注釋)方法是實用和有用的,并且不會導致任何設計問題。但是,如果您喜歡其他方法,ABP也支持 FluentValidation集成。

      有關所有驗證選項,請參 閱驗證文檔

      輸出DTO最佳實踐

      • 保持輸出DTO計數最小。在可能的情況下重用(例外:不要將輸入dto重用為輸出dto)
      • 輸出dto可以包含比客戶端代碼中使用的更多的屬性。
      • 從創建和更新方法返回實體DTO。

      這些建議的主要目的是:

      • 使客戶端代碼易于開發和擴展

        1. 在客戶端處理類似但不相同的dto是有問題的
        2. 將來在UI/客戶端上添加其他屬性是很常見的。返回實體的所有屬性(通過考慮安全性和特權)使客戶端代碼很容易改進,而不需要接觸后端代碼
        3. 如果你將API開放給第三方客戶,而你不知道每個客戶的需求
      • 使服務器端代碼易于開發和擴展

        1. 你需要理解和維護的類更少
        2. 您可以重用 Entity->DTO 對象映射代碼
        3. 從不同的方法返回相同的類型使創建新方法變得簡單明了

      示例:從不同的方法返回不同的dto

      public interface IUserAppService : IApplicationService
      {
          UserDto Get(Guid id);
          List<UserNameAndEmailDto> GetUserNameAndEmail(Guid id);
          List<string> GetRoles(Guid id);
          List<UserListDto> GetList();
          UserCreationResultDto Create(UserCreationDto input);
          UserUpdateResultDto Update(UserUpdateDto input);
      }
      

      (我們沒有使用異步方法使示例更清晰,但在您的實際應用程序中使用異步!)

      上面的示例代碼為每個方法返回不同的DTO類型。您可以猜到,在查詢數據、將實體映射到dto時,會有很多代碼重復

      上面的IUserAppService服務可以被簡化:

      public interface IUserAppService : IApplicationService
      {
          UserDto Get(Guid id);
          List<UserDto> GetList();
          UserDto Create(UserCreationDto input);
          UserDto Update(UserUpdateDto input);
      }
      

      統一使用單個輸出DTO:

      public class UserDto
      {
          public Guid Id { get; set; }
          public string UserName { get; set; }
          public string Email { get; set; }
          public DateTime CreationTime { get; set; }
          public List<string> Roles { get; set; }
      }
      
      • 刪除了GetUserNameAndEmail 和 GetRoles,因為Get方法已經返回必要的信息
      • GetList 現在與Get返回相同的結果
      • 創建和更新也返回相同的UserDto

      如前所述,使用相同的輸出DTO有許多優點。例如,設想一個場景,您在UI上顯示一個Users數據網格。在更新用戶之后,您可以獲得返回值并在UI上更新它。你不需要再調用GetList。這就是為什么我們建議返回實體DTO(這里是UserDto)作為創建和更新操作的返回值

      討論

      有些輸出DTO建議可能不適合所有場景。由于性能原因,可以忽略這些建議,特別是當返回的數據集很大,或者當您為自己的UI創建服務時,您有太多的并發請求

      在這些情況下,您可能希望創建包含最少信息的專用輸出dto。以上建議特別適用于那些維護代碼庫比忽略不計的性能損失更重要的應用程序

      對象映射

      當兩個對象具有相同或相似的屬性時,自動 對象映射 是將值從一個對象復制到另一個對象的有用方法

      DTO和實體類通常具有相同/相似的屬性,通常需要從實體創建DTO對象。ABP的 對象映射系統AutoMapper 集成使得這些操作比手動映射更容易。

      • 只對實體使用自動對象映射來輸出DTO映射
      • 不要對輸入DTO到實體的映射使用自動對象映射。

      有一些原因不應該使用輸入DTO來進行實體自動映射:

      • 實體類通常有一個接受參數并確保有效創建對象的構造函數。自動對象映射操作通常需要一個空的構造函數
      • 大多數實體屬性將具有私有設置器,您應該使用方法以可控的方式更改這些屬性
      • 您通常需要仔細地驗證和處理用戶/客戶端輸入,而不是盲目地映射到實體屬性

      雖然其中一些問題可以通過映射配置來解決(例如,AutoMapper允許定義自定義映射規則),但它使您的業務代碼隱式/隱藏,并與基礎設施緊密耦合。我們認為業務代碼應該是明確的、清晰的和容易理解的

      請參閱下面的 創建實體 一節,以獲得本節建議的示例實現。

      posted @ 2022-06-23 17:50  Broadm  閱讀(292)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 午夜免费福利小电影| 影音先锋大黄瓜视频| 人妻无码∧V一区二区| 亚洲国产中文字幕在线视频综合| 日韩AV高清在线看片| 国产欧美精品区一区二区三区| 亚洲欧洲无码av电影在线观看| 亚洲av成人一区国产精品| 色综合天天综合网国产人| 色秀网在线观看视频免费| 日韩在线视频网| 中文字幕在线无码一区二区三区 | 97精品伊人久久久大香线蕉| 女同另类激情在线三区| 久久月本道色综合久久| 亚洲一精品一区二区三区| 少妇撒尿一区二区在线视频| 久久香蕉国产线看观看怡红院妓院| 无码国产偷倩在线播放老年人| 亚洲av专区一区| 久久一区二区中文字幕| 福利一区二区在线观看| 亚洲永久一区二区三区在线 | 亚洲夂夂婷婷色拍WW47| 老司机亚洲精品一区二区| 亚洲AV无码秘?蜜桃蘑菇| 亚洲午夜成人精品电影在线观看 | 不卡国产一区二区三区| 日本怡春院一区二区三区| 色一乱一伦一图一区二区精品| 亚洲欧美自偷自拍视频图片| 白嫩日本少妇做爰| 亚洲成a人v欧美综合天堂下载| 欧美经典人人爽人人爽人人片| 国产成人av一区二区三| 影音先锋啪啪av资源网站| 大香伊蕉在人线国产av| 久久99亚洲网美利坚合众国| VA在线看国产免费| 国产在线拍揄自揄视频网试看| 国偷自产一区二区三区在线视频|