AutoMapper 简介

AutoMapper是一个对象映射器,它可以将一种类型的对象转换为另一种类型的对象。

它提供了映射规则及操作方法,使我们不用过多配置就可以映射两个类, 可以帮我们免于编写无聊的映射代码. 在代码层与层之间隔离模型model上非常有用.

AutoMapper 使用

初始化

创建两个简单的类用于测试:

public class UserEntity
{
public int Id { get; set; }
public string Name { get; set; }
} public class UserDTO
{
public int Id { get; set; }
public string Name { get; set; }
}

AutoMapper可以使用静态类和实例方法来创建映射.

  • 静态类方式

    Mapper.Initialize(cfg => cfg.CreateMap<UserEntity, UserDTO>());
    var userDTO = Mapper.Map<UserDTO>(user);
  • 实例方式

    var config = new MapperConfiguration(cfg => cfg.CreateMap<UserEntity, UserDTO>());
    var mapper = config.CreateMapper(); var userDTO = mapper.Map<UserDTO>(user);
  • 依赖注入

    使用扩展 AutoMapper.Extensions.Microsoft.DependencyInjection 来实现AutoMapper的依赖注入. 本质是注册一个MapperConfiguration的单例和IMapper的scope实例, 通过程序集扫描添加AutoMapper的相关配置和映射.

    IServiceCollection services = new ServiceCollection();
    services.AddAutoMapper(); var provider = services.BuildServiceProvider();
    using (var scope = provider.CreateScope())
    {
    var mapper = scope.ServiceProvider.GetService<IMapper>();
    var userDTO = mapper.Map<UserDTO>(user);
    }

Profile设置

可以使用Profie配置来实现映射关系, 然后通过AddProfile添加.

public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>();
}
} var config = new MapperConfiguration(cfg => cfg.AddProfile<UserProfile>());

扁平化映射

AutoMapper支持扁平化映射, 它会根据Pascal命名方式分割目标字段为单个单词, 可自动映射属性名+内嵌属性名. 如下例AutoMapper自动映射UserEntity.Address.City -> UserDTO.AddressCity。

public class UserEntity
{
public int Id { get; set; }
public string Name { get; set; } public Address Address { get; set; }
} public class Address
{
public string City { get; set; }
public string Country { get; set; }
} public class UserDTO
{
public int Id { get; set; }
public string Name { get; set; }
public string AddressCity { get; set; }
public string AddressCountry { get; set; }
}

集合映射

AutoMapper除了可以映射单个对象外,也可以映射集合对象。

CreateMap<UserEntity, UserDTO>();

var userList = new List<UserEntity> {
new UserEntity { Id = 1, Name="Test1" },
new UserEntity { Id = 2, Name="Test2" },
};
var dtoList = mapper.Map<List<UserDTO>>(userList);
public class UserEntity
{
public int Id { get; set; }
public string Name { get; set; } public List<AddressEntity> AddressList { get; set; }
} public class AddressEntity
{
public string City { get; set; }
public string Country { get; set; }
} public class UserDTO
{
public int Id { get; set; }
public string Name { get; set; } public List<AddressDTO> AddressList { get; set; }
} public class AddressDTO
{
public string City { get; set; }
public string Country { get; set; }
} CreateMap<AddressEntity, AddressDTO>();
CreateMap<UserEntity, UserDTO>(); var user = new UserEntity
{
Id = 1,
Name = "Test",
AddressList = new List<AddressEntity>
{
new AddressEntity { City = "ShangHai", Country = "China"},
new AddressEntity { City = "BeiJing", Country = "China"}
}
}; var userDTO = mapper.Map<UserDTO>(user);

投影

当把一个源值投影到一个不精准匹配源结构的目标值时,使用MapFrom指明成员映射定义。

public class UserEntity
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime BirthDate { get; set; }
} public class UserDTO
{
public int Id { get; set; }
public string Name { get; set; }
public string BirthYear { get; set; }
public string BirthMonth { get; set; }
} public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.ForMember(d => d.BirthYear, o => o.MapFrom(s => s.BirthDate.Year))
.ForMember(d => d.BirthMonth, o => o.MapFrom(s => s.BirthDate.Month));
}
} var user = new UserEntity
{
Id = 1,
Name = "Test",
BirthDate = DateTime.Today,
}; var userDTO = mapper.Map<UserDTO>(user);

条件映射

有些情况下,我们将只满足映射条件的才添加到属性上.

public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.ForMember(d => d.Id, o => o.Condition(s => s.Id > 1));
}
}

值转换

AutoMapper可以配置值转换和空值替换

public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.ForMember(d => d.Name, o => o.NullSubstitute("Default Name"))
.ForMember(d => d.Name, o => o.AddTransform(val => string.Format("Name: {0}", val)));
}
}

设置转换前后行为

有时候,在映射发生之前或之后,可能需要执行一些自定义的逻辑。

public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.BeforeMap((s, d) => s.BirthDate = s.BirthDate.AddYears(-12))
.AfterMap((s, d) => d.BirthMonth = "July");
}
}

配置验证及设置

配置了映射,但是如何确定是否映射成功或者是否有字段没有映射呢?可以使用mapper.ConfigurationProvider.AssertConfigurationIsValid()来验证是否映射成功。但也可以指定单个字段不验证.

public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.ForMember(d => d.NickName, o => o.Ignore());
}
}

反向映射

从6.1.0开始,AutoMapper通过ReverseMap可以实现反向映射。使用ReverseMap, 不用再创建DTO -> Entity的映射, 而且还能保留正向的映射规则。

public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.ReverseMap();
}
}

自定义转换器

有些情况下目标字段类型和源字段类型不一致,可以通过类型转换器实现映射,类型转换器有三种实现方式:

void ConvertUsing(Func<TSource, TDestination> mappingFunction);
void ConvertUsing(ITypeConverter<TSource, TDestination> converter);
void ConvertUsing<TTypeConverter>() where TTypeConverter : ITypeConverter<TSource, TDestination>;

自定义解析器

某些情况下,解析规则会很复杂,使用自带的解析规则无法实现。这时可以自定义解析规则,可以通过以下三种方式使用自定义的解析器:

ResolveUsing<TValueResolver>
ResolveUsing(typeof(CustomValueResolver))
ResolveUsing(aValueResolverInstance)
public class UserEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
} public class UserDTO
{
public string Name { get; set; }
} public class UserNameResolver : IValueResolver<UserEntity, UserDTO, string>
{
public string Resolve(UserEntity source, UserDTO destination, string destMember, ResolutionContext context)
{
if (source != null && !string.IsNullOrEmpty(source.FirstName) && !string.IsNullOrEmpty(source.LastName))
{
return string.Format("{0} {1}", source.FirstName, source.LastName);
} return string.Empty;
}
} public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDTO>()
.ForMember(d => d.Name, o => o.ResolveUsing<UserNameResolver>());
}
}

参考

ASP.NET Core 中的对象映射之 AutoMapper的更多相关文章

  1. 在Asp .net core 中通过属性映射实现动态排序和数据塑形

    目录 属性映射服务实现 动态排序 数据塑形 属性映射服务实现 public class PropertyMappingValue { public IEnumerable<string> ...

  2. ASP.NET CORE 中使用AutoMapper进行对象映射

    ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...

  3. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  4. ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射

    本章主要简单介绍下在ASP.NET Core中如何使用AutoMapper进行实体映射.在正式进入主题之前我们来看下几个概念: 1.数据库持久化对象PO(Persistent Object):顾名思义 ...

  5. ASP.NET Core中如何针对一个使用HttpClient对象的类编写单元测试

    原文地址: How to unit test a class that consumes an HttpClient with IHttpClientFactory in ASP.NET Core? ...

  6. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  7. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

  8. ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态

    原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...

  9. ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】

    本系列前面的文章我们主要以编程的角度对ASP.NET Core的依赖注入系统进行了详细的介绍,如果读者朋友们对这些内容具有深刻的理解,我相信你们已经可以正确是使用这些与依赖注入相关的API了.如果你还 ...

随机推荐

  1. Delphi for iOS开发指南(4):在iOS应用程序中使用不同风格的Button组件

    http://blog.csdn.net/DelphiTeacher/article/details/8923481 在FireMonkey iOS应用程序中的按钮 FireMoneky定义了不同类型 ...

  2. 自适应XAML布局经验总结 (二) 局部布局设计模式1

    本系列对实际项目中的XAML布局场景进行总结,给出了较优化的自适应布局解决方案,希望对大家有所帮助. 下面开始介绍局部布局设计模式. 1. 工具栏模式 适用于工具栏,标题等的布局. 此块布局区域外层使 ...

  3. paxos ---学习笔记

    摘自维基百科:分布式系统中的节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing).基于消息传递通信模型的分布式系统,不可避免的会发生以下错误:进程 ...

  4. mysql免安装版 安装配置 (转)

    1. 下载MySQL Community Server 5.6.13 2. 解压MySQL压缩包     将以下载的MySQL压缩包解压到自定义目录下,我的解压目录是:     "D:\Pr ...

  5. Javascript设计模式理论与实战:状态模式

    在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将其抽象出来称为状态,我们平时开发时本质上就是对应用程序的各种状态进行切换并作出相应处理.状态模式就是一种适合多种状态场景下的设计模式 ...

  6. 3D空间中射线与三角形的交叉检测算法【转】

    引言 射线Ray,在3D图形学中有很多重要的应用.比如,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检测等等都可以使用射线Ray来完成.所以,在本次博客中,将会简单的像大家介绍下,如 ...

  7. [翻译]NUnit---Property and Random Attributes(十四)

    小记:由于工作琐碎,没得心情翻译而且也在看<CLR vis C#>,所以断更了差不多5个月,现在继续翻译,保证会翻译完成,不会虎头蛇尾. 另:NUnit已经更新到2.6.3版本,虽然正在开 ...

  8. 避免图片路径访问405,可以用图片控件来显示局部相对路径,不需要域名就不会出现jpg静态资源访问错误

    <asp:Image ID="Image1" runat="server"/> protected void Page_Load(object se ...

  9. sql-省市区

    insert into Area (codeid,parentid,cityName) values(11,0,'北京');insert into Area (codeid,parentid,city ...

  10. 关于文件的INode与Java中的文件操作接口

    本文由作者周梁伟授权网易云社区发布. 近日做的项目中涉及到多进程共同读写多个文件的问题,文件名和最后修改时间都是可能会被频繁修改的,因而识别文件的唯一性会产生相当的麻烦,于是专门再学习了一下文件系统对 ...