.Net Core 常用类库 AutoMapper
1 AutoMapper
同一个数据实体,在不同场合需要转换成不同模式的情况
映射两个对象之间的映射,一般是数据模型映射到视图模型,如果没有AutoMapper 需要手动处理费时费力
包 AutoMapper
同名部分大小写会自动映射
/// <summary> /// 映射源 /// </summary> public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } } /// <summary> /// 映射对象 /// </summary> public class StudentViewModel { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } }
public class Sample02 { public static void Run() { //映射使用的基本方法 Student 映射源 StudentViewModel映射目标 var config = new MapperConfiguration(cfg => cfg.CreateMap<Student, StudentViewModel>()); var mapper = config.CreateMapper(); var result = GetStudents(); var students = mapper.Map<List<StudentViewModel>>(result); Print(students); } public static List<Student> GetStudents() { // 通过上下稳 var context = new SampleContext(); return context.Students; } public static void Print(IList<StudentViewModel> studentViewModels) { foreach (var student in studentViewModels) { Console.WriteLine($"Id={student.Id};Name={student.Name};Age={student.Age};Gender={student.Gender}"); } } }
有结构的类型映射(扁平化映射)
/// <summary> /// 源数据1 /// </summary> public class User { public int Id { get; set; } public string Name { get; set; } public Address Address { get; set; } } /// <summary> ///源数据2 /// </summary> public class Address { public string City { get; set; } public string State { get; set; } public string Country { get; set; } } /// <summary> /// 视图模型 (目标模型) /// </summary> public class UserViewModel { public int Id { get; set; } public string Name { get; set; } public string City { get; set; } public string State { get; set; } public string Country { get; set; } }
public class Sample03 { public static void Run() { var config = new MapperConfiguration(cfg => { cfg.CreateMap<User, UserViewModel>() .ForMember( model => model.City,//指定的目标 expression => expression.MapFrom(user => user.Address.City))//指定源 .ForMember( model => model.Country, expression => expression.MapFrom(user => user.Address.Country)) .ForMember( model => model.State, expression => expression.MapFrom(user => user.Address.State)); }); var mapper = config.CreateMapper(); var result = GetUsers(); var users = mapper.Map<List<UserViewModel>>(result); Print(users); } public static List<User> GetUsers() { var context = new SampleContext(); return context.Users; } public static void Print(IList<UserViewModel> userViewModels) { foreach (var user in userViewModels) { Console.WriteLine($"Id={user.Id};Name={user.Name};City={user.City}"); } } }
如果扁平化映射配置很多 如何方便管理:
使用Profile
public class UserProfile : Profile { public UserProfile() { CreateMap<User, UserViewModel>() .ForMember( model => model.City, expression => expression.MapFrom(user => user.Address.City)) .ForMember( model => model.State, expression => expression.MapFrom(user => user.Address.State)) .ForMember( model => model.Country, expression => expression.MapFrom(user => user.Address.Country)); } } public class StudentProfile : Profile { public StudentProfile() { CreateMap<Student, StudentViewModel>(); } }
public class Sample04 { public static void Run() { var config = new MapperConfiguration(cfg => { //只需要添加这个配置对象就可以了 cfg.AddProfile<UserProfile>(); cfg.AddProfile<StudentProfile>(); //还可以使用扫描的方式 //cfg.AddMaps(Assembly.GetExecutingAssembly()); }); var mapper = config.CreateMapper(); var result = GetUsers(); var users = mapper.Map<List<UserViewModel>>(result); Print(users); } public static List<User> GetUsers() { var context = new SampleContext(); return context.Users; } public static void Print(IList<UserViewModel> userViewModels) { foreach (var user in userViewModels) { Console.WriteLine($"Id={user.Id};Name={user.Name};City={user.City}"); } } }
最终如何结合到asp.net core 中使用呢?
/// <summary> /// 订单 /// </summary> public class Order { public Guid Id { get; set; } public DateTime DateOrder { get; set; } public int Quantity { get; set; } public double Amount { get; set; } public Guid ProductId { get; set; } public Product Product { get; set; } } /// <summary> /// 产品 /// </summary> public class Product { public Guid Id { get; set; } public string Name { get; set; } }
/// <summary> /// 仓储类 /// </summary> public class OrderRepository { private readonly SampleContext _context; public OrderRepository(SampleContext context) { _context = context; } public Order GetById(Guid id) { var order = _context.Orders.FirstOrDefault(o => o.Id == id); order.Product = _context.Products.FirstOrDefault(p => p.Id == order.ProductId); return order; } } /// <summary> /// 查询处理器 /// </summary> public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdRequestModel, GetOrderByIdResponseModel> { private readonly OrderRepository _orderRepository; private readonly IMapper _mapper; public GetOrderByIdQueryHandler(OrderRepository orderRepository, IMapper mapper) { _orderRepository = orderRepository; _mapper = mapper; } public Task<GetOrderByIdResponseModel> Handle(GetOrderByIdRequestModel request, CancellationToken cancellationToken) { var order = _orderRepository.GetById(request.OrderId); //这里使用autoMapper var response = _mapper.Map<GetOrderByIdResponseModel>(order); return Task.FromResult(response); } } /// <summary> /// Profile /// </summary> public class OrderProfile : Profile { public OrderProfile() { CreateMap<Order, GetOrderByIdResponseModel>(); } }
/// <summary> /// 响应模式 /// </summary> public class GetOrderByIdResponseModel { public Guid Id { get; set; } public DateTime DateOrder { get; set; } public int Quantity { get; set; } public double Amount { get; set; } //注意这种情况 如果在扁平化映射中这种情况是可以自动映射,是由源数据类的类名和属性命结合的情况,这是AutoMapper的默认约定 public Guid ProductId { get; set; } public string ProductName { get; set; } }
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); //上下文 services.AddSingleton<SampleContext>(); //仓储 services.AddScoped<OrderRepository>(); //注入AutoMapper服务 参数指定了程序集 会自动获取其中的Profile services.AddAutoMapper(Assembly.GetExecutingAssembly()); services.AddMediatR(Assembly.GetExecutingAssembly()); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
AutoMapper 自定义解析映射例子:
/// <summary> /// 源 /// </summary> public class Customer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } /// <summary> /// 映射类视图 /// </summary> public class CustomerViewModel { public int Id { get; set; } public string FullName { get; set; } } /// <summary> /// 解析类定义 Customer源 CustomerViewModel映射对象(目标 ) string解析后的数据类型 /// </summary> public class CustomerResolver : IValueResolver<Customer, CustomerViewModel, string> { public string Resolve(Customer source, CustomerViewModel destination, string destMember, ResolutionContext context) { return source.FirstName + " " + source.LastName; } }
public class Sample05 { public static void Run() { var config = new MapperConfiguration(cfg => { cfg.CreateMap<Customer, CustomerViewModel>() .ForMember(model => model.FullName, expression => expression.MapFrom<CustomerResolver>()); }); var mapper = config.CreateMapper(); var customer = new Customer { Id = 1, FirstName = "Klein", LastName = "Moretti" }; var result = mapper.Map<CustomerViewModel>(customer); Console.WriteLine(result.FullName); } }
AutoMapper 自定义类型转换映射 例子:
/// <summary> /// 源类型 /// </summary> public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } /// <summary> /// 目标类型 /// </summary> public class PersonViewModel { public int Id { get; set; } public string Name { get; set; } /// <summary> /// 类型和源类型不匹配 /// </summary> public string Age { get; set; } } /// <summary> /// 类型转换器 /// </summary> public class StringTypeConverter : ITypeConverter<int, string> { public string Convert(int source, string destination, ResolutionContext context) { return source.ToString(); } }
public class Sample06 { public static void Run() { var config = new MapperConfiguration(cfg => { //先定义转换器 cfg.CreateMap<int, string>().ConvertUsing<StringTypeConverter>(); cfg.CreateMap<Person, PersonViewModel>(); }); var mapper = config.CreateMapper(); var person = new Person { Id = 1, Age = 10 }; var result = mapper.Map<PersonViewModel>(person); Console.WriteLine($"{result.Age.GetType()}:Age={result.Age})"); } }
AutoMapper动态类型转换映射 的例子
public class Sample07 { public static void Run() { var config = new MapperConfiguration(cfg => {}); var mapper = config.CreateMapper(); var customer = new Customer { Id = 1, FirstName = "Klein", LastName = "Moretti" }; // 强类型对象映射到动态类型对象 var result = mapper.Map<dynamic>(customer); Console.WriteLine($"result:{result.FirstName} {result.LastName}"); // 动态类型对象映射到强类型对象 customer = mapper.Map<Customer>(result); Console.WriteLine($"customer:{customer.FirstName} {customer.LastName}"); // 字典对象映射到强类型对象 var dict = new Dictionary<string, object> {{"FirstName", "Klein"}, {"LastName", "Moretti"}}; customer = mapper.Map<Customer>(dict); Console.WriteLine($"dictToCustomer:{customer.FirstName} {customer.LastName}"); } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战