上一篇文章(https://www.cnblogs.com/meowv/p/12961014.html)整合了定時任務處理框架Hangfire,完成了一個簡單的定時任務處理解決方案。
本篇緊接著來玩一下AutoMapper,AutoMapper可以很方便的搞定我們物件到物件之間的對映關係處理,同時abp也幫我們是現實了IObjectMapper
介面,先根據官方文件:https://docs.abp.io/zh-Hans/abp/latest/Object-To-Object-Mapping ,將AutoMapper新增依賴到專案中。
在.Application
層模組類中新增AbpAutoMapperModule
模組依賴。
//MeowvBlogApplicationModule.cs
using Meowv.Blog.Application.Caching;
using Volo.Abp.AutoMapper;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
namespace Meowv.Blog.Application
{
[DependsOn(
typeof(AbpIdentityApplicationModule),
typeof(AbpAutoMapperModule),
typeof(MeowvBlogApplicationCachingModule)
)]
public class MeowvBlogApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
...
}
}
}
在本專案中,主要處理的就是實體和DTO之前的對映關係,以之前寫的BlogService.cs
中的增刪改查為例,將Post.cs
和PostDto.cs
互相對映。
先看GetPostAsync(int id)
這個方法,之前的做法是手動建立物件,然後為其一個一個的賦值,可以想象當我們的欄位超級多的時候,都得寫一遍。現在有了AutoMapper,一句程式碼就可以搞定。
public async Task<ServiceResult<PostDto>> GetPostAsync(int id)
{
var result = new ServiceResult<PostDto>();
var post = await _postRepository.GetAsync(id);
if (post == null)
{
result.IsFailed("文章不存在");
return result;
}
//var dto = new PostDto
//{
// Title = post.Title,
// Author = post.Author,
// Url = post.Url,
// Html = post.Html,
// Markdown = post.Markdown,
// CategoryId = post.CategoryId,
// CreationTime = post.CreationTime
//};
var dto = ObjectMapper.Map<Post, PostDto>(post);
result.IsSuccess(dto);
return result;
}
ObjectMapper
在ApplicationService
中已經被注入,我們的繼承了ServiceBase
,可以直接使用。
到這裡還沒完,其中最重要的一步就是定義類與類之間的對映關係,AutoMapper提供了多種定義類之間對映的方法,有關詳細資訊請參閱AutoMapper的文件:https://docs.automapper.org/
其中定義一種對映的方法是建立一個Profile 類,在.Application
層新增MeowvBlogAutoMapperProfile.cs
,直接繼承Profile
在建構函式中定義即可。
//MeowvBlogAutoMapperProfile.cs
using AutoMapper;
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.Domain.Blog;
namespace Meowv.Blog.Application
{
public class MeowvBlogAutoMapperProfile : Profile
{
public MeowvBlogAutoMapperProfile()
{
CreateMap<Post, PostDto>();
CreateMap<PostDto, Post>().ForMember(x => x.Id, opt => opt.Ignore());
}
}
}
定義兩個規則,第一個:從Post
對映到PostDto
,因為PostDto
所有屬性在Post
中都是存在的,所以直接CreateMap<>
即可;第二個:從PostDto
對映到Post
,因為Post
中存在Id屬性,而在PostDto
中是沒有的,所以可以使用ForMember(...)
來忽略掉Id屬性。
定義好對映規則後,在模組類中新增使用。
//MeowvBlogApplicationModule.cs
...
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<MeowvBlogApplicationModule>(validate: true);
options.AddProfile<MeowvBlogAutoMapperProfile>(validate: true);
});
}
...
使用同樣的方式修改一下InsertPostAsync(PostDto dto)
方法的程式碼。
public async Task<ServiceResult<string>> InsertPostAsync(PostDto dto)
{
var result = new ServiceResult<string>();
//var entity = new Post
//{
// Title = dto.Title,
// Author = dto.Author,
// Url = dto.Url,
// Html = dto.Html,
// Markdown = dto.Markdown,
// CategoryId = dto.CategoryId,
// CreationTime = dto.CreationTime
//};
var entity = ObjectMapper.Map<PostDto, Post>(dto);
var post = await _postRepository.InsertAsync(entity);
if (post == null)
{
result.IsFailed("新增失敗");
return result;
}
result.IsSuccess("新增成功");
return result;
}
解放了雙手,程式碼也變少了,真香,去測試一下用了物件對映後的介面是否好使。
可以看到,結果也是可以出來的,後續都將按照上面的方法大量用到物件對映。
順便介紹.HttpApi.Hosting
層幾個配置屬性。
路由規則配置,預設Swagger中的路由是大寫的,如果我想轉成小寫可以使用以下配置程式碼,都寫在模組類MeowvBlogHttpApiHostingModule.cs
中。
public override void ConfigureServices(ServiceConfigurationContext context)
{
...
context.Services.AddRouting(options =>
{
// 設定URL為小寫
options.LowercaseUrls = true;
// 在生成的URL後面新增斜槓
options.AppendTrailingSlash = true;
});
...
}
使用HSTS的中介軟體,該中介軟體新增了嚴格傳輸安全頭。
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
...
app.UseHsts();
...
}
直接使用預設的跨域配置。
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
...
app.UseCors();
...
}
HTTP請求轉HTTPS。
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
...
app.UseHttpsRedirection();
...
}
轉發將標頭代理到當前請求,配合 Nginx 使用,獲取使用者真實IP。
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
...
pp.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
...
}
本篇介紹瞭如何使用AutoMapper,搞定物件到物件間的對映,篇幅簡短,內容比較簡單,你學會了嗎????