您现在的位置是:网站首页> 编程资料编程资料
.NET 6开发TodoList应用之使用AutoMapper实现GET请求_实用技巧_
2023-05-24
405人已围观
简介 .NET 6开发TodoList应用之使用AutoMapper实现GET请求_实用技巧_
需求
需求很简单:实现GET请求获取业务数据。在这个阶段我们经常使用的类库是AutoMapper。
目标
合理组织并使用AutoMapper,完成GET请求。
原理与思路
首先来简单地介绍一下这这个类库。
关于AutoMapper
在业务侧代码和数据库实体打交道的过程中,一个必不可少的部分就是返回的数据类型转换。对于不同的请求来说,希望得到的返回值是数据库实体的一部分/组合/计算等情形。我们就经常需要手写用于数据对象转换的代码,但是转换前后可能大部分情况下有着相同名称的字段或属性。这部分工作能避免手写冗长的代码吗?可以。
我们希望接受的请求和返回的值(统一称为model)具有以下两点需要遵循的原则:
1.每个model被且只被一个API消费;
2.每个model里仅仅包含API发起方希望包含的必要字段或属性。
AutoMapper库就是为了实现这个需求而存在的,它的具体用法请参考官方文档,尤其是关于Convention的部分,避免重复劳动。
实现
所有需要使用AutoMapper的地方都集中在Application项目中。
引入AutoMapper
$ dotnet add src/TodoList.Application/TodoList.Application.csproj package AutoMapper.Extensions.Microsoft.DependencyInjection
然后在Application/Common/Mappings下添加配置,提供接口的原因是我们后面就可以在DTO里实现各自对应的Mapping规则,方便查找。
IMapFrom.cs
using AutoMapper; namespace TodoList.Application.Common.Mappings; public interface IMapFrom{ void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType()); }
MappingProfile.cs
using System.Reflection; using AutoMapper; namespace TodoList.Application.Common.Mappings; public class MappingProfile : Profile { public MappingProfile() => ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly()); private void ApplyMappingsFromAssembly(Assembly assembly) { var types = assembly.GetExportedTypes() .Where(t => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>))) .ToList(); foreach (var type in types) { var instance = Activator.CreateInstance(type); var methodInfo = type.GetMethod("Mapping") ?? type.GetInterface("IMapFrom`1")!.GetMethod("Mapping"); methodInfo?.Invoke(instance, new object[] { this }); } } } 在DependencyInjection.cs进行依赖注入:
DependencyInjection.cs
// 省略其他... services.AddAutoMapper(Assembly.GetExecutingAssembly()); services.AddMediatR(Assembly.GetExecutingAssembly()); return services;
实现GET请求
在本章中我们只实现TodoList的Query接口(GET),并且在结果中包含TodoItem集合,剩下的接口后面的文章中逐步涉及。
GET All TodoLists
在Application/TodoLists/Queries/下新建一个目录GetTodos用于存放创建一个TodoList相关的所有逻辑:
定义TodoListBriefDto对象:
TodoListBriefDto.cs
using TodoList.Application.Common.Mappings; namespace TodoList.Application.TodoLists.Queries.GetTodos; // 实现IMapFrom接口,因为此Dto不涉及特殊字段的Mapping规则 // 并且属性名称与领域实体保持一致,根据Convention规则默认可以完成Mapping,不需要额外实现 public class TodoListBriefDto : IMapFrom { public Guid Id { get; set; } public string? Title { get; set; } public string? Colour { get; set; } }
GetTodosQuery.cs
using AutoMapper; using AutoMapper.QueryableExtensions; using MediatR; using Microsoft.EntityFrameworkCore; using TodoList.Application.Common.Interfaces; namespace TodoList.Application.TodoLists.Queries.GetTodos; public class GetTodosQuery : IRequest> { } public class GetTodosQueryHandler : IRequestHandler
> { private readonly IRepository _repository; private readonly IMapper _mapper; public GetTodosQueryHandler(IRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; } public async Task > Handle(GetTodosQuery request, CancellationToken cancellationToken) { return await _repository .GetAsQueryable() .AsNoTracking() .ProjectTo
(_mapper.ConfigurationProvider) .OrderBy(t => t.Title) .ToListAsync(cancellationToken); } }
最后实现Controller层的逻辑:
TodoListController.cs
// 省略其他... [HttpGet] public async Task>> Get() { return await _mediator.Send(new GetTodosQuery()); }
GET Single TodoList
首先在Application/TodoItems/Queries/下新建目录GetTodoItems用于存放获取TodoItem相关的所有逻辑:
定义TodoItemDto和TodoListDto对象:
TodoItemDto.cs
using AutoMapper; using TodoList.Application.Common.Mappings; using TodoList.Domain.Entities; namespace TodoList.Application.TodoItems.Queries.GetTodoItems; // 实现IMapFrom接口 public class TodoItemDto : IMapFrom { public Guid Id { get; set; } public Guid ListId { get; set; } public string? Title { get; set; } public bool Done { get; set; } public int Priority { get; set; } // 实现接口定义的Mapping方法,并提供除了Convention之外的特殊字段的转换规则 public void Mapping(Profile profile) { profile.CreateMap () .ForMember(d => d.Priority, opt => opt.MapFrom(s => (int)s.Priority)); } }
TodoListDto.cs
using TodoList.Application.Common.Mappings; using TodoList.Application.TodoItems.Queries.GetTodoItems; namespace TodoList.Application.TodoLists.Queries.GetSingleTodo; // 实现IMapFrom接口,因为此Dto不涉及特殊字段的Mapping规则 // 并且属性名称与领域实体保持一致,根据Convention规则默认可以完成Mapping,不需要额外实现 public class TodoListDto : IMapFrom { public Guid Id { get; set; } public string? Title { get; set; } public string? Colour { get; set; } public IList Items { get; set; } = new List (); }
创建一个根据ListId来获取包含TodoItems子项的spec:
TodoListSpec.cs
using Microsoft.EntityFrameworkCore; using TodoList.Application.Common; namespace TodoList.Application.TodoLists.Specs; public sealed class TodoListSpec : SpecificationBase{ public TodoListSpec(Guid id, bool includeItems = false) : base(t => t.Id == id) { if (includeItems) { AddInclude(t => t.Include(i => i.Items)); } } }
我们仍然为这个查询新建一个GetSingleTodo目录,并实现GetSIngleTodoQuery:
GetSingleTodoQuery.cs
using AutoMapper; using AutoMapper.QueryableExtensions; using MediatR; using Microsoft.EntityFrameworkCore; using TodoList.Application.Common.Interfaces; using TodoList.Application.TodoLists.Specs; namespace TodoList.Application.TodoLists.Queries.GetSingleTodo; public class GetSingleTodoQuery : IRequest{ public Guid ListId { get; set; } } public class ExportTodosQueryHandler : IRequestHandler { private readonly IRepository _repository; private readonly IMapper _mapper; public ExportTodosQueryHandler(IRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; } public async Task Handle(GetSingleTodoQuery request, CancellationToken cancellationToken) { var spec = new TodoListSpec(request.ListId, true); return await _repository .GetAsQueryable(spec) .AsNoTracking() .ProjectTo (_mapper.ConfigurationProvider) .FirstOrDefaultAsync(cancellationToken); } }
添加Controller逻辑,这里的Name是为了完成之前遗留的201返回的问题,后文会有使用。
TodoListController.cs
// 省略其他... [HttpGet("{id:Guid}", Name = "TodListById")] public async Task> GetSingleTodoList(Guid id) { return await _mediator.Send(new GetSingleTodoQuery { ListId = id }) ?? throw new InvalidOperationException(); } 验证
运行Api项目
获取所有TodoList列表
请求

响应
提示:
本文由神整理自网络,如有侵权请联系本站删除!
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!
相关内容
- .Net使用分表分库框架ShardingCore实现多字段分片_实用技巧_
- .NET 6开发TodoList应用之实现Repository模式_实用技巧_
- .NET 6开发TodoList应用之使用MediatR实现POST请求_实用技巧_
- .NET 6开发TodoList应用引入数据存储_实用技巧_
- .NET 6开发TodoList应用引入第三方日志库_实用技巧_
- .NET 6开发TodoList应用实现结构搭建_实用技巧_
- .NET 6开发TodoList应用实现系列背景_实用技巧_
- 浅析.netcore中的Configuration具体使用_实用技巧_
- Visual Studio 2022智能辅助编码介绍_实用技巧_
- 正确使用dotnet-*工具的方法_实用技巧_
