我有一个具有下划线命名约定的DTO对象,我希望将其映射到具有Pascal大小写命名约定的DB实体。我有问题映射属性与名称中的数字。下面是一个最小可复制示例:
using AutoMapper;
MapperConfiguration config =
new(cfg =>
{
cfg.SourceMemberNamingConvention = PascalCaseNamingConvention.Instance;
cfg.DestinationMemberNamingConvention = LowerUnderscoreNamingConvention.Instance;
cfg.CreateMap<MyDbEntity, MyDto>().ReverseMap();
});
config.AssertConfigurationIsValid();
IMapper mapper = config.CreateMapper();
// dto.equip_crest_slot_type_1_crest_id_1 = 10
MyDto dto = mapper.Map<MyDto>(new MyDbEntity() { EquipCrestSlotType1CrestId1 = 10 });
// dbEntry.EquipCrestSlotType1CrestId1 = 0
MyDbEntity dbEntry = mapper.Map<MyDbEntity>(dto);
public class MyDto
{
public int equip_crest_slot_type_1_crest_id_1 { get; set; }
}
public class MyDbEntity
{
public int EquipCrestSlotType1CrestId1 { get; set; }
}
当从DTO创建DB实体时,该属性被忽略了,这很奇怪,因为它是单向映射的。我想知道如果问题是ReverseMap()
不验证,我可以看到,如果我做一个实际的反向配置文件:
using AutoMapper;
MapperConfiguration config =
new(cfg =>
{
cfg.SourceMemberNamingConvention = LowerUnderscoreNamingConvention.Instance;
cfg.DestinationMemberNamingConvention = PascalCaseNamingConvention.Instance;
cfg.CreateMap<MyDto, MyDbEntity>();
});
config.AssertConfigurationIsValid();
得到一个异常
Unhandled exception. AutoMapper.AutoMapperConfigurationException:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
====================
MyDto -> MyDbEntity (Destination member list)
MyDto -> MyDbEntity (Destination member list)
Unmapped properties:
EquipCrestSlotType1CrestId1
我不知道为什么一个配置文件会以一种方式工作,而不是另一种方式,但我认为问题是我误解了Pascal案例应该如何工作,当数字在属性名称的中间。从客户端接收lower_underscore名称,我无法控制它们,但是我可以重命名数据库实体.
是否有一种方法可以解决这个问题,而无需手动分配成员?我使用的是AutoMapper 12.0.0。
如果默认命名约定在您的特定用例中不起作用,您总是可以替换它。问题是PascalCaseNamingConvention
将名称标记为["Equip", "Crest", "Slot", "Type1", "Crest" "Id1"]
,而不是将数字作为单独的标记,因为LowerUnderscoreNamingConvention
在下划线名称中。
在这种情况下,您可以创建一个与现有PascalCaseNamingConvention
略有不同的类,它具有以下源代码:
public sealed class PascalCaseNamingConvention : INamingConvention
{
public static readonly PascalCaseNamingConvention Instance = new();
public string SeparatorCharacter => "";
public string[] Split(string input)
{
List<string> result = null;
int lower = 0;
for(int index = 1; index < input.Length; index++)
{
if (char.IsUpper(input[index]))
{
result ??= new();
result.Add(input[lower..index]);
lower = index;
}
}
if (result == null)
{
return Array.Empty<string>();
}
result.Add(input[lower..]);
return result.ToArray();
}
}
只需更改Split
函数,将数字分别标记。