AutoMapper 枚举映射
内置的枚举映射器不可配置,只能被替换。作为替代方案,AutoMapper 在一个独立的包 AutoMapper.Extensions.EnumMapping 中支持基于约定的枚举值映射功能。
使用方法
对于 CreateMap
方法,这个库提供了一个 ConvertUsingEnumMapping
方法。此方法会添加从源枚举到目标枚举值的所有默认映射。
如果你想更改某些映射,则可以使用 MapValue
方法。这是一个可链式调用的方法。
默认情况下,枚举值按值(明确地说是:MapByValue()
)映射,但也可以通过调用 MapByName()
来按名称映射。
using AutoMapper.Extensions.EnumMapping;
public enum Source
{
Default = 0,
First = 1,
Second = 2
}
public enum Destination
{
Default = 0,
Second = 2
}
internal class YourProfile : Profile
{
public YourProfile()
{
CreateMap<Source, Destination>()
.ConvertUsingEnumMapping(opt => opt
// 可选:.MapByValue() 或 MapByName(),如果不进行配置,默认使用 MapByValue
.MapValue(Source.First, Destination.Default)
)
.ReverseMap(); // 支持从 Destination 到 Source 的映射,包括 ConvertUsingEnumMapping 的自定义映射
}
}
...
默认约定
包 AutoMapper.Extensions.EnumMapping 会将源类型的所有值映射到目标类型,如果这两个枚举类型具有相同的值(或按名称或按值)。所有没有目标等价物的源枚举值,在启用 EnumMappingValidation 时,将会抛出异常。
ReverseMap 约定
对于 ReverseMap
方法,使用的约定与默认映射相同,但它也会尊重可能的枚举值映射覆盖。
确定反向覆盖的步骤如下:
为
Source
到Destination
创建映射(使用默认约定),包括自定义覆盖。为
Destination
到Source
创建映射(使用默认约定),不包括自定义覆盖(需要确定)。步骤 1 中创建的映射将用于确定
ReverseMap
的覆盖。因此,映射将按Destination
值分组。3a) 如果有匹配的 `Source` 值对应于 `Destination` 值,则优先选择该映射,不需要覆盖。
可能存在一个
Destination
值对应多个通过覆盖映射指定的Source
值。我们必须确定哪个
Source
值将成为当前Destination
值(现在是新的Source
值)的新Destination
。对于每个按
Destination
值分组的Source
值:3b) 如果 `Source` 枚举值在 `Destination` 枚举类型中不存在,则该映射无法反转。 3c) 如果有不是步骤1中映射部分的 `Source` 值,则该映射无法反转。 3d) 如果 `Source` 值未被选项b和c排除,则该 `Source` 值就是新的 `Destination` 值。
步骤 3 中确定的所有覆盖将应用于步骤 2 中的映射。
最后,提供给
ReverseMap
方法的自定义映射将被应用。
测试
AutoMapper 提供了验证类型映射的便捷工具。这个包添加了一个额外的 EnumMapperConfigurationExpressionExtensions.EnableEnumMappingValidation
扩展方法,以扩展现有的 AssertConfigurationIsValid()
方法来同时验证枚举映射配置。
为了启用枚举映射配置的测试:
public class MappingConfigurationsTests
{
[Fact]
public void WhenProfilesAreConfigured_ItShouldNotThrowException()
{
// Arrange
var config = new MapperConfiguration(configuration =>
{
configuration.EnableEnumMappingValidation();
configuration.AddMaps(typeof(AssemblyInfo).GetTypeInfo().Assembly);
});
// Assert
config.AssertConfigurationIsValid();
}
}