日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

roslyn分析字符串代码_.NET 5 源代码生成器——MediatR——CQRS

發布時間:2025/3/8 asp.net 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 roslyn分析字符串代码_.NET 5 源代码生成器——MediatR——CQRS 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在這篇文章中,我們將探索如何使用.NET 5中的新source generator特性,使用MediatR庫和CQRS模式自動為系統生成API。

中介者模式

中介模式是在應用程序中解耦模塊的一種方式。在基于web的應用程序中,它通常用于將前端與業務邏輯的解耦。

在.NET平臺上,MediatR庫是該模式最流行的實現之一。如下圖所示,中介器充當所發送命令的發送方和接收方之間的中間人。發送者不知道也不關心誰在處理命令。

使用MediatR,我們定義了一個command,它實現IRequest接口,其中T表示返回類型。在這個例子中,我們有一個CreateUser類,它將返回一個字符串給調用者:

public class CreateUser : IRequest<string>{ public string id { get; set; } public string Name { get; set; }}

從ASP.NET Core API發送命令到MediatR,我們可以使用以下代碼:

[Route("api/[controller]")][ApiController]public class CommandController : ControllerBase{ private readonly IMediator _mediator; public CommandController(IMediator mediator) { _mediator = mediator; } [HttpPost] public async Task<string> Get(CreateUser command) { return await _mediator.Send(command); }}

在接收端,實現也非常簡單:創建一個實現IRequestHandler接口的類。在本例中,我們有一個處理程序,它處理CreateUser并向調用者返回一個字符串:

public class CommandHandlers : IRequestHandlerstring={ public Task<string> Handle(CreateUser request, CancellationToken cancellationToken) { return Task.FromResult("User Created"); }}

每個處理程序類可以處理多個命令。處理規則是對于一個特定的命令,應該總是只有一個處理程序。如果希望將消息發送給許多訂閱者,則應該使用MediatR中的內置通知功能,但在本例中我們將不使用該功能。

CQRS

Command Query Responsibility Segregation(CQRS)是一個非常簡單的模式。它要求我們應該將系統中的命令(寫)的實現與查詢(讀)分離開來。

有了CQRS,我們會從這樣做:

改為這樣做:

CQRS通常與event sourcing相關聯,但是使用CQRS并不需要使用event sourcing,而僅僅使用CQRS本身就會給我們帶來很多架構上的優勢。這是為什么呢?因為讀寫的需求通常是不同的,所以它們需要單獨的實現。

Mediator + CQRS

在示例應用程序中結合這兩種模式,我們可以創建如下的架構:

?Command和Query

使用MediatR,Command和Query之間沒有明顯的分離,因為兩者都將實現IRequest接口。為了更好地分離它們,我們將引入以下接口:?

public interface ICommand<T> : IRequest<T>{}public interface IQuery<T> : IRequest<T>{}

下面是使用這兩個接口的示例:

public record CreateOrder : ICommand<string>{ public int Id { get; set; } public int CustomerId { get; set; }}public record GetOrder : IQuery{ public int OrderId { get; set; }}

為了進一步改進我們的代碼,我們可以使用新的C# 9?record特性。在內部,它仍然是一個類,但是我們為我們生成了很多樣板代碼,包括equality, GetHashCode, ToString……

?前端Command和Query

要真正從外部接收Command和Query,我們需要創建一個ASP.NET Core API。這些action方法將接收傳入的HTTP命令,并將它們傳遞給MediatR以進行進一步處理。控制器可能是這樣的:

[Route("api/[controller]")][ApiController]public class CommandController : ControllerBase{ private readonly IMediator _mediator; public CommandController(IMediator mediator) { _mediator = mediator; } [HttpPost] public async Task<string> CreateOrder([FromBody] CreateOrder command) { return await _mediator.Send(command); } [HttpPost] public async TaskGetOrder([FromBody] GetOrder command) { return await _mediator.Send(command); }}

然后,MediatR將把Command和Query傳遞給各種處理程序,這些處理程序將處理它們并返回響應。應用CQRS模式,我們將為Command和Query處理程序使用單獨的類。

public class CommandHandlers : IRequestHandlerstring={ public Task<string> Handle(CreateOrder request, CancellationToken ct) { return Task.FromResult("Order created"); }}public class QueryHandlers : IRequestHandler"">{ public Task Handle(GetOrder request, CancellationToken ct) { return Task.FromResult(new Order() { Id = 2201, CustomerId = 1234, OrderTotal = 9.95m, OrderLines = new List() }); }}

源代碼生成器?

這是Roslyn編譯器中的一個新特性,它允許我們hook到編譯器,并在編譯過程中生成額外的代碼。

在一個非常高的層次上,你可以看到它如下:

  • 首先,編譯器編譯你的C#源代碼并生成語法樹。
  • 然后,源代碼生成器可以檢查這個語法樹并生成新的C#源代碼。
  • 然后,這個新的源代碼被編譯并添加到最終的輸出中。
  • 重要的是要知道源代碼生成器永遠不能修改現有的代碼,它只能向應用程序添加新代碼。

    源代碼生成器+MediatR+CQRS

    對于我們實現的每個Command和Query,我們必須編寫相應的ASP.NET Core action方法。

    這意味著如果我們的系統中有50個Command和Query,我們需要創建50個action方法。當然,這將是相當乏味的、重復的和容易出錯的。

    但是,如果僅僅基于Command/Query,我們就可以生成API代碼作為編譯的一部分,這不是很酷嗎?就像這樣:

    意思是,如果我創建這個Command類:

    /// /// Create a new order/// /// /// Send this command to create a new order in the system for a given customer/// public record CreateOrder : ICommand<string>{ /// /// OrderId /// /// This is the customers internal ID of the order. /// 123 [Required] public int Id { get; set; } /// /// CustomerID /// /// 1234 [Required] public int CustomerId { get; set; }}

    然后,源生成器將生成以下類,作為編譯的一部分:

    /// /// This is the controller for all the commands in the system/// [Route("api/[controller]/[Action]")][ApiController]public class CommandController : ControllerBase{ private readonly IMediator _mediator; public CommandController(IMediator mediator) { _mediator = mediator; } /// /// Create a new order /// /// /// Send this command to create a new order in the system for a given customer /// /// An instance of the CreateOrder /// The status of the operation /// Returns the newly created item /// If the item is null [HttpPost] [Produces("application/json")] [ProducesResponseType(typeof(string), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task<string> CreateOrder([FromBody] CreateOrder command) { return await _mediator.Send(command); }}

    使用OpenAPI生成API文檔

    幸運的是是Swashbuckle包含在ASP.NET Core 5的API模板默認情況下,會看到這些類并為我們生成漂亮的OpenAPI (Swagger)文檔!

    看看我的代碼

    他是這樣組成的:

    • SourceGenerator

    ? ? ?這個項目包含實際的源生成器,它將生成API控制器action方法。

    • SourceGenerator-MediatR-CQRS

  • 這是一個使用源代碼生成器的示例應用程序。查看項目文件,以了解該項目如何引用源生成器。

  • Templates這個文件夾包含Command和Query類的模板。源代碼生成器將把生成的代碼插入到這些模板中。

  • CommandAndQueries基于此文件夾中定義的Command和Query,生成器將生成相應的ASP.NET終結點。

  • 查看生成的代碼

    我們如何看到生成的源代碼?通過將這些行添加到API項目文件中,我們可以告訴編譯器將生成的源代碼寫到我們選擇的文件夾中:

    <EmitCompilerGeneratedFiles> TrueEmitCompilerGeneratedFiles><CompilerGeneratedFilesOutputPath> $(BaseIntermediateOutputPath)\GeneratedFilesCompilerGeneratedFilesOutputPath>

    ?這意味著你可以在這個目錄中找到生成的代碼:

    \obj\GeneratedFiles\SourceGenerator\SourceGenerator.MySourceGenerator

    在這個文件夾里你會找到以下兩個文件:

    結論

    通過引入源代碼生成器的概念,我們可以刪除大量必須編寫和維護的樣板代碼。我不是編譯器工程師,我在源代碼生成器方面的方法可能不是100%最優的(甚至不是100%正確的),但它仍然表明任何人都可以創建自己的源代碼生成器,而沒有太多麻煩。

    ?歡迎關注我的公眾號,如果你有喜歡的外文技術文章,可以通過公眾號留言推薦給我。

    總結

    以上是生活随笔為你收集整理的roslyn分析字符串代码_.NET 5 源代码生成器——MediatR——CQRS的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。