亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

.NET?6開發(fā)TodoList應(yīng)用之使用MediatR實(shí)現(xiàn)POST請(qǐng)求

 更新時(shí)間:2021年12月27日 14:46:29   作者:CODE4NOTHING  
對(duì)于稍微正式的項(xiàng)目,.NET工程上習(xí)慣的實(shí)現(xiàn)是通過使用比較成熟的類庫框架,有效地對(duì)業(yè)務(wù)邏輯進(jìn)行分類管理、消除冗余代碼,以達(dá)到業(yè)務(wù)邏輯職責(zé)清晰簡潔的目的。在這個(gè)階段我們經(jīng)常使用的兩個(gè)類庫分別是AutoMapper和MediatR。本文將為大家介紹MediatR如何實(shí)現(xiàn)POST請(qǐng)求

需求

需求很簡單:如何創(chuàng)建新的TodoListTodoItem并持久化。

初學(xué)者按照教程去實(shí)現(xiàn)的話,應(yīng)該分成以下幾步:創(chuàng)建Controller并實(shí)現(xiàn)POST方法;實(shí)用傳入的請(qǐng)求參數(shù)new一個(gè)數(shù)據(jù)庫實(shí)體對(duì)象;調(diào)用IRepository<T>完成數(shù)據(jù)庫的寫入,最多會(huì)在中間加一層Service。這個(gè)做法本身沒有問題,也是需要從初學(xué)階段開始扎實(shí)地掌握開發(fā)技能的必經(jīng)之路,有助于幫助理解邏輯調(diào)用的過程。

對(duì)于稍微正式一些的項(xiàng)目,.NET工程上習(xí)慣的實(shí)現(xiàn)是通過使用一些比較成熟的類庫框架,有效地對(duì)業(yè)務(wù)邏輯進(jìn)行分類管理、消除冗余代碼,以達(dá)到業(yè)務(wù)邏輯職責(zé)清晰簡潔的目的。在這個(gè)階段我們經(jīng)常使用的兩個(gè)類庫分別是AutoMapperMediatR,本文結(jié)合POST請(qǐng)求,先介紹關(guān)于MediatR部分,下一篇關(guān)于GET請(qǐng)求,會(huì)涉及AutoMapper的部分。

目標(biāo)

合理組織并使用MediatR,完成POST請(qǐng)求。

原理與思路

首先來簡單地介紹一下這個(gè)類庫。

關(guān)于CQRS模式、中介者模式和MediatR

CQRS模式

CQRS模式全稱是“Command Query Responsibility Segregation”,正如字面意思,CQRS模式的目的在于將讀取操作和寫入操作的指責(zé)區(qū)分開,并使用不同的Model去表示。從CRUD的角度來說,就是把RCUD區(qū)分開來對(duì)待。如下圖所示:

這個(gè)模式可以有效地應(yīng)用到具有主從分離的數(shù)據(jù)庫架構(gòu)中,當(dāng)需要獲取數(shù)據(jù)時(shí),從只讀數(shù)據(jù)庫(一般是從庫)中讀取數(shù)據(jù),當(dāng)需要寫入或更新數(shù)據(jù)時(shí),向主庫進(jìn)行操作。

CQRS模式旨在解決的問題是:為了屏蔽數(shù)據(jù)庫層面“寫優(yōu)先”還是“讀優(yōu)先”的優(yōu)化設(shè)計(jì)策略,在業(yè)務(wù)邏輯側(cè)進(jìn)行解耦。

任何設(shè)計(jì)模式都是對(duì)解決特定問題的一個(gè)Trade off,自然也帶來了一些缺點(diǎn),首先就是服務(wù)內(nèi)部的組件復(fù)雜度上升了,因?yàn)樾枰獎(jiǎng)?chuàng)建額外的類來實(shí)現(xiàn)CQRS模式;其次如果數(shù)據(jù)層是分離的,那么可能會(huì)有數(shù)據(jù)的狀態(tài)不一致問題。

中介者M(jìn)ediator模式

這是23種基本設(shè)計(jì)模式中的一個(gè),屬于行為型設(shè)計(jì)模式,它給出了組件之間交互的一種解耦的方式。簡單參考下圖,具體內(nèi)容就不過多解釋了,任何一篇介紹設(shè)計(jì)模式的文章都有介紹。

這種設(shè)計(jì)模式實(shí)際上是一種采用依賴倒置(Inversion of Control, IoC)的方式,實(shí)現(xiàn)了圖中藍(lán)色組件的松耦合。

MediatR

這是在開發(fā)中被廣泛采用的實(shí)現(xiàn)以上兩種設(shè)計(jì)模式的類庫,更準(zhǔn)確的說法是,它通過應(yīng)用中介者模式,實(shí)現(xiàn)了進(jìn)程內(nèi)CQRS。基本思想是所有來自API接口和數(shù)據(jù)存儲(chǔ)之間的邏輯,都需要通過MediatR來組織(即所謂的“中介者”)。

從實(shí)現(xiàn)上看,MediatR提供了幾組用于不同場景的接口,我們在本文中處理的比較多的是IRequest<T>/IRequestHandler<T>以及INotification<T>/INotificationHander<T>兩組接口,更多的請(qǐng)參考官方文檔和例子。

實(shí)現(xiàn)

所有需要使用MediatR的地方都集中在Application項(xiàng)目中。

引入MediatR

$ dotnet add src/TodoList.Application/TodoList.Application.csproj package MediatR.Extensions.Microsoft.DependencyInjection

為了適配CQRS的模式,我們在Application項(xiàng)目中的TodoLists和TodoItems下相同地創(chuàng)建幾個(gè)文件夾:

Commands:用于組織CUD相關(guān)的業(yè)務(wù)邏輯;

Queries:用于組織R相關(guān)的業(yè)務(wù)邏輯;

EventHandlers:用于組織領(lǐng)域事件處理的相關(guān)業(yè)務(wù)邏輯。

Application根目錄下同樣創(chuàng)建DependencyInjection.cs用于該項(xiàng)目的依賴注入:

DependencyInjection.cs

using System.Reflection;

using Microsoft.Extensions.DependencyInjection;



namespace TodoList.Application;



public static class DependencyInjection

{

    public static IServiceCollection AddApplication(this IServiceCollection services)

    {

        services.AddMediatR(Assembly.GetExecutingAssembly());

        return services;

    }

}

并在Api項(xiàng)目中使用:

// 省略其他...
// 添加應(yīng)用層配置
builder.Services.AddApplication();
// 添加基礎(chǔ)設(shè)施配置
builder.Services.AddInfrastructure(builder.Configuration);

實(shí)現(xiàn)Post請(qǐng)求

在本章中我們只實(shí)現(xiàn)TodoListTodoItem的Create接口(POST),剩下的接口后面的文章中逐步涉及。

POST TodoList

Application/TodoLists/Commands/下新建一個(gè)目錄CreateTodoList用于存放創(chuàng)建一個(gè)TodoList相關(guān)的所有邏輯:

CreateTodoListCommand.cs

using MediatR;

using TodoList.Application.Common.Interfaces;



namespace TodoList.Application.TodoLists.Commands.CreateTodoList;



public class CreateTodoListCommand : IRequest<Guid>

{

    public string? Title { get; set; }

}



public class CreateTodoListCommandHandler : IRequestHandler<CreateTodoListCommand, Guid>

{

    private readonly IRepository<Domain.Entities.TodoList> _repository;



    public CreateTodoListCommandHandler(IRepository<Domain.Entities.TodoList> repository)

    {

        _repository = repository;

    }



    public async Task<Guid> Handle(CreateTodoListCommand request, CancellationToken cancellationToken)

    {

        var entity = new Domain.Entities.TodoList

        {

            Title = request.Title

        };



        await _repository.AddAsync(entity, cancellationToken);

        return entity.Id;

    }

}

有一些實(shí)踐是將RequestRequestHandler分開兩個(gè)文件,我更傾向于像這樣將他倆放在一起,一是保持簡潔,二是當(dāng)你需要順著一個(gè)Command去尋找它對(duì)應(yīng)的Handler時(shí),不需要更多的跳轉(zhuǎn)。

接下來在TodoListController里實(shí)現(xiàn)對(duì)應(yīng)的POST方法,

using MediatR;

using Microsoft.AspNetCore.Mvc;

using TodoList.Application.TodoLists.Commands.CreateTodoList;



namespace TodoList.Api.Controllers;



[ApiController]

[Route("/todo-list")]

public class TodoListController : ControllerBase

{

    private readonly IMediator _mediator;



    // 注入MediatR

    public TodoListController(IMediator mediator)

        => _mediator = mediator;



    [HttpPost]

    public async Task<Guid> Create([FromBody] CreateTodoListCommand command)

    {

        var createdTodoList = await _mediator.Send(command);



        // 出于演示的目的,這里只返回創(chuàng)建出來的TodoList的Id,

        // 實(shí)際使用中可能會(huì)選擇IActionResult作為返回的類型并返回CreatedAtRoute對(duì)象,

        // 因?yàn)槲覀冞€沒有去寫GET方法,返回CreatedAtRoute會(huì)報(bào)錯(cuò)(找不到對(duì)應(yīng)的Route),等講完GET后會(huì)在那里更新

        return createdTodoList.Id;

    }

}

POST TodoItem

類似TodoListController和CreateTodoListCommand的實(shí)現(xiàn),這里我直接把代碼貼出來了。

CreateTodoItemCommand.cs

using MediatR;

using TodoList.Application.Common.Interfaces;

using TodoList.Domain.Entities;

using TodoList.Domain.Events;



namespace TodoList.Application.TodoItems.Commands.CreateTodoItem;



public class CreateTodoItemCommand : IRequest<Guid>

{

    public Guid ListId { get; set; }



    public string? Title { get; set; }

}



public class CreateTodoItemCommandHandler : IRequestHandler<CreateTodoItemCommand, Guid>

{

    private readonly IRepository<TodoItem> _repository;



    public CreateTodoItemCommandHandler(IRepository<TodoItem> repository)

    {

        _repository = repository;

    }



    public async Task<Guid> Handle(CreateTodoItemCommand request, CancellationToken cancellationToken)

    {

        var entity = new TodoItem

        {

            // 這個(gè)ListId在前文中的代碼里漏掉了,需要添加到Domain.Entities.TodoItem實(shí)體上

            ListId = request.ListId,

            Title = request.Title,

            Done = false

        };



        await _repository.AddAsync(entity, cancellationToken);



        return entity.Id;

    }

}

TodoItemController.cs

using MediatR;

using Microsoft.AspNetCore.Mvc;

using TodoList.Application.TodoItems.Commands.CreateTodoItem;



namespace TodoList.Api.Controllers;



[ApiController]

[Route("/todo-item")]

public class TodoItemController : ControllerBase

{

    private readonly IMediator _mediator;



    // 注入MediatR

    public TodoItemController(IMediator mediator) 

        => _mediator = mediator;



    [HttpPost]

    public async Task<Guid> Create([FromBody] CreateTodoItemCommand command)

    {

        var createdTodoItem = await _mediator.Send(command);



        // 處于演示的目的,這里只返回創(chuàng)建出來的TodoItem的Id,理由同前

        return createdTodoItem.Id;

    }

}

驗(yàn)證

運(yùn)行Api項(xiàng)目,通過Hoppscotch發(fā)送對(duì)應(yīng)接口請(qǐng)求:

創(chuàng)建TodoList驗(yàn)證

請(qǐng)求

返回

數(shù)據(jù)庫

第一條數(shù)據(jù)是種子數(shù)據(jù),第二條是我們剛才創(chuàng)建的。

創(chuàng)建TodoItem驗(yàn)證

繼續(xù)拿剛才創(chuàng)建的這個(gè)TodoList的Id來創(chuàng)建新的TodoItem:

請(qǐng)求

返回

數(shù)據(jù)庫

最后一條是我們新創(chuàng)建的,其余是種子數(shù)據(jù)。

總結(jié)

我們已經(jīng)通過演示在POST請(qǐng)求中實(shí)現(xiàn)MediatR庫帶來的CQRS模式,在這篇文章里我留了一個(gè)坑。就是領(lǐng)域事件的Handler并沒有任何演示,只是創(chuàng)建了一個(gè)文件夾,結(jié)合在這篇文章中留下來的發(fā)布領(lǐng)域事件的坑,會(huì)在DELETE的文章中填完。

看起來使用CQRS模式使得我們的代碼結(jié)構(gòu)變得更加復(fù)雜了,但是對(duì)于一些再復(fù)雜一些的實(shí)際項(xiàng)目中,正確使用CQRS模式有助于你分析和整理業(yè)務(wù)需求,并將相關(guān)的業(yè)務(wù)需求以及相關(guān)模型梳理到統(tǒng)一的位置進(jìn)行管理,包括在后續(xù)的文章里我們會(huì)陸續(xù)向其中加入諸如入?yún)⑿r?yàn)、出參類型轉(zhuǎn)換等邏輯。認(rèn)真思考并運(yùn)用習(xí)慣之后,大家可以自行體會(huì)這樣做的“權(quán)衡”。

參考資料

MediatR

Mediator?

以上就是.NET 6開發(fā)TodoList應(yīng)用之使用MediatR實(shí)現(xiàn)POST請(qǐng)求的詳細(xì)內(nèi)容,更多關(guān)于.NET 6 MediatR實(shí)現(xiàn)POST請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論