c# - 这是 AutoMapper 的 PascalCase 命名约定正则表达式的错误吗?
问题描述
我正在尝试利用 AutoMapper,以便不必手动编写大量代码映射。这似乎适用于除这一类以外的所有内容:
CreateMap<AccountConnection, AccountConnectionDto>();
CreateMap<Account, AccountDto>();
CreateMap<Address, AddressDto>() // <--- this one
.ForMember(dest => dest.StreetAddress1, opt => opt.MapFrom(src => src.street_address_1))
.ForMember(dest => dest.StreetAddress2, opt => opt.MapFrom(src => src.street_address_2))
.ForMember(dest => dest.StreetAddress3, opt => opt.MapFrom(src => src.street_address_3));
如果我不手动映射这 3 个成员,那么当我运行config.AssertConfigurationIsValid();
它时会抛出。
Exception Details: 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
=================================================
Address -> AddressDto (Destination member list)
Proj.Data.Address -> Proj.API.AddressDto (Destination member list)
Unmapped properties:
StreetAddress1
StreetAddress2
StreetAddress3
我在我的个人资料中使用以下命名约定:
SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
DestinationMemberNamingConvention = new PascalCaseNamingConvention();
这些是属性名称中唯一带有数字的属性,因此我深入研究了 GitHub 上的 AutoMapper 源代码,并找到了我在项目中使用的 PascalCaseNamingConvention 的正则表达式。这是:
(\p{Lu}+(?=$|\p{Lu}[\p{Ll}0-9])|\p{Lu}?[\p{Ll}0-9]+)
如果我将其放入https://regex101.com,然后根据我的属性名称对其进行测试,ShippingAddress1
我会得到两个匹配项,Shipping
并且Address1
.
鲁鲁!我的源属性名称是shipping_address_1
(不要问),所以这不起作用。这是因为我的命名约定被破坏了,还是 PascalCaseNamingConvention 应该shipping_address_x
匹配ShippingAddressX
?(去 AutoMapper github 上提出一个问题,但他们要求新手先在 SO 上发帖,看看人们是否认为这是一个合法的错误)。
解决方案
从下面详述的测试中,我认为指定的命名约定是错误的:
public class Address
{
public string StreetAddress1 { get; set; }
}
public class AddressDto
{
public string street_address_1 { get; set; }
}
static void Main(string[] args)
{
// Prints nothing
PerformMappingTest(new PascalCaseNamingConvention(), new LowerUnderscoreNamingConvention());
// Prints "Test"
PerformMappingTest(new LowerUnderscoreNamingConvention(), new PascalCaseNamingConvention());
Console.ReadKey();
}
static void PerformMappingTest(INamingConvention source, INamingConvention destination)
{
var config = new MapperConfiguration(cfg => {
cfg.SourceMemberNamingConvention = source;
cfg.DestinationMemberNamingConvention = destination;
cfg.CreateMap<Address, AddressDto>();
});
var mapper = config.CreateMapper();
var address = new Address { StreetAddress1 = "Test" };
var addressDto = mapper.Map<Address, AddressDto>(address);
Console.WriteLine(addressDto.street_address_1);
}
推荐阅读
- gpu - 将数据从计算管道的输出资源传输到 DirectX 12 中的交换链图像?
- javascript - Discord.js 清除命令跳过固定消息
- git - git diff 没有差异,但由于行尾改变不应该有一些差异?
- kernel - 现代计算机系统(x86 架构)是否具有独立于操作系统的虚拟寻址?
- python - 什么是 tensorflow.python.data.ops.dataset_ops._OptionsDataset?
- c# - 类的 foreach 函数
- spring-boot - 我正在尝试使用 Spring webflux 使用弹性搜索 API 以使我的 API 端点非阻塞
- c# - 有没有办法从另一个进程“GetCommandLineArgs”?
- python - 在生成器表达式或 for 循环中使用 python lambda
- python - 从 Python 中打开的类似文件的对象解析 Mbox?