呈上篇,我們已經將驗證透過IPipelineBehavior
進行簡化了,以下是目前的程式碼
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IMediator _mediator;
public WeatherForecastController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
public async Task<IActionResult> CreateWeatherForecast(
[FromBody] CreateWeatherForecastRequest request)
{
var command = new CreateWeatherForecastCommand
{
Nation = request.Nation,
City = request.City,
Date = request.Date,
TemperatureC = request.TemperatureC,
Summary = request.Summary,
};
var result = await _mediator.Send(command);
return result ? Ok() : BadRequest();
}
[HttpPut("{id:int}")]
public async Task<IActionResult> UpdateWeatherForecast(int id,
[FromBody] UpdateWeatherForecastRequest request)
{
if (id != request.WeatherForecastId) return BadRequest();
var command = new UpdateWeatherForecastCommand
{
WeatherForecastId = request.WeatherForecastId,
Nation = request.Nation,
City = request.City,
Date = request.Date,
TemperatureC = request.TemperatureC,
Summary = request.Summary,
};
var result = await _mediator.Send(command);
return result ? Ok() : BadRequest();
}
}
其中我們可以看到CreateWeatherForecastRequest
與CreateWeatherForecastCommand
,兩個類別高度重複
// CreateWeatherForecastRequest.cs 類別
public class CreateWeatherForecastRequest
{
public string Nation { get; set; }
public string City { get; set; }
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
}
// CreateWeatherForecastCommand.cs 類別
public class CreateWeatherForecastCommand : ICommand<bool>
{
public string Nation { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
}
有部分範例會直接使用 Command 取代 Request,但這會造成高層元件依賴低層。當然在簡單的專案上,是否需要完整切割,還是看個人與團隊的共識,減少類別與簡化實作也是一個選擇。
而本篇介紹另一個套件,AutoMapper,該套件已經存在數十年之久,也有相當多的專案採用與文章介紹,前幾篇有提到 AutoMapper 和 MediatR 均是出自 Jimmy Bogard 這位大神的手中,深遠的影響著大大小小的專案,該作者的Blog,也提出相當多,值得學習的觀點,包括 Repository 層是否實作的爭議。
由於相關介紹文章已經很多了,這邊只快速帶過,介紹導入步驟。
官方告知從版本 13.0 開始,AddAutoMapper
成為核心包的一部分,並且 DI 套件將停止使用。然而寫這篇的時候,最新版本為 12.0.1,所以我們還是安裝了AutoMapper.Extensions.Microsoft.DependencyInjection
,才能使用AddAutoMapper
個人習慣會開一個 Mappers 資料夾,然後設定一個AutoMappers
空類別,內部依照類別+Profile命名。
public class AutoMappers
{
}
public class WeatherForecastProfile : Profile
{
public WeatherForecastProfile()
{
CreateMap<CreateWeatherForecastRequest, CreateWeatherForecastCommand>();
CreateMap<UpdateWeatherForecastRequest, UpdateWeatherForecastCommand>();
}
}
// 其他類別的 Mapper Instances
//public class LocationProfile : Profile
//{
// public LocationProfile()
// {
// CreateMap<TSourece,TDestination> ...
// }
//}
IServiceCollection
註冊builder.Services.AddAutoMapper(typeof(AutoMappers));
IMapper