简体   繁体   中英

Is this a bug with AutoMapper's PascalCase naming convention regex?

I'm attempting to leverage AutoMapper in order to not have to manually write a lot of code mappings. This appears to be working fine for everything other than this one class:

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));

If I don't manually map those 3 members, then when I run config.AssertConfigurationIsValid(); it throws.

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

I am using the following naming conventions in my profile:

SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
DestinationMemberNamingConvention = new PascalCaseNamingConvention();

These are the only properties with numbers in the property name so I dug in to the AutoMapper source on GitHub and found the Regex for the PascalCaseNamingConvention that I'm using in my project. It is:

(\\p{Lu}+(?=$|\\p{Lu}[\\p{Ll}0-9])|\\p{Lu}?[\\p{Ll}0-9]+) If I throw that in https://regex101.com and then test it against my property name ShippingAddress1 I get two matches, Shipping and Address1 .

Ruh-roh! My source property name is shipping_address_1 (Don't ask) so that isn't going to work. Is this because my naming convention is broken, or should the PascalCaseNamingConvention match shipping_address_x to ShippingAddressX ? (Went to raise an issue on the AutoMapper github but they ask newcomers to post on SO first, to see if people think it is a legitimate bug or not).

From my testing detailed below, I believe the naming conventions specified are the wrong way around:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM