简体   繁体   English

AutoMapper定制-将字符串映射到DTO

[英]AutoMapper customization - Mapping strings to DTO

I have the following models: 我有以下型号:

public class AccountDto
{
    public Guid Id { get; set; }
    public string ChamberOfCommerce { get; set; }
    public string Code { get; set; }
    public VatDto PurchaseVatCode { get; set; }
    public VatDto SalesVatCode { get; set; }
}

public class VatDto
{
    public string Code { get; set; }
    public string Description { get; set; }
    public double Percentage { get; set; }
}

public class Account
{
    public Guid Id { get; set; }
    public string ChamberOfCommerce { get; set; }
    public string Code { get; set; }

    public string PurchaseVatCode { get; set; }
    public string PurchaseVatDescription { get; set; }
    public double PurchaseVatPercentage { get; set; }

    public string SalesVatCode { get; set; }
    public string SalesVatDescription { get; set; }
    public double SalesVatPercentage { get; set; }
}

I want to read the data in flat mode and then map it to the AccountDto . 我想以平面模式读取数据,然后将其映射到AccountDto I tried to configure the AutoMapper using following lines: 我尝试使用以下几行来配置AutoMapper:

var config = new MapperConfiguration(cfg => {
    cfg.AddMemberConfiguration()
       .AddMember<NameSplitMember>()
       .AddName<PrePostfixName>(_ => _.AddStrings(p => p.Prefixes, "Purchase", "Sales"))
       .AddName<ReplaceName>(_ => _.AddReplace("Purchase", string.Empty).AddReplace("Sales", string.Empty));
    cfg.RecognizePrefixes("Purchase");
    cfg.RecognizePrefixes("Sales");
    cfg.RecognizeDestinationPrefixes("Purchase");
    cfg.RecognizeDestinationPrefixes("Sales");
    cfg.CreateMap<AccountDto, Models.Account>().ReverseMap();
});

var mapper = config.CreateMapper();
var dto = mapper.Map<AccountDto>(account);

But none of the above attempts worked and I still can't map the PurchaseVatCode . 但是以上尝试均无济于事,我仍然无法映射PurchaseVatCode

I get the following error: 我收到以下错误:

Property:
PurchaseVatCode ---> 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
String -> VatDto (Destination member list)
System.String -> Online.Account.Domain.Dto.VatDto (Destination member list)

Unmapped properties:
Code
Description
TranslatedDescription
Percentage

Can anyone help with this issue? 谁能解决这个问题? Thanks in advance! 提前致谢!

All the difficulties originate from the very bad choice of AccountDto property names PurchaseVatCode and SalesVatCode . 所有困难都源于AccountDto属性名称PurchaseVatCodeSalesVatCode错误选择。 In order to let AutoMapper correctly flatten the names, we need to strip Code suffix. 为了使AutoMapper正确拼合名称,我们需要去除Code后缀。

The problem is that the Account has properties with the same name but different type. 问题在于该Account具有名称相同但类型不同的属性。 So we can't use RecognizeAlias to rename them because it will rename the target property as well. 因此,我们不能使用RecognizeAlias重命名它们,因为它也会重命名target属性。

The only methods that are separate for source and target are for specifying prefix/suffix. 源和目标分开的唯一方法是指定前缀/后缀。 But if we use RecognizeSuffix("Code") in order to strip Code from source PurchaseVatCode and SalesVatCode , that unfortunately affects the VatDto.Code property as well (this probably can be considered a current AutoMapper defect). 但是,如果我们使用RecognizeSuffix("Code")以便从源PurchaseVatCodeSalesVatCode剥离Code ,那么不幸的是,这VatDto.Code影响VatDto.Code属性(这可能被视为当前的AutoMapper缺陷)。

The best you can do in this scenario is to use the later to do the most of the job and explicitly map the Code properties: 在这种情况下,您可以做的最好的事情就是使用后者来完成大部分工作并显式映射Code属性:

var config = new MapperConfiguration(cfg =>
{
    cfg.RecognizePostfixes("Code");

    cfg.CreateMap<AccountDto, Account>()
        .ForMember(dst => dst.PurchaseVatCode, opt => opt.MapFrom(src => src.PurchaseVatCode.Code))
        .ForMember(dst => dst.SalesVatCode, opt => opt.MapFrom(src => src.SalesVatCode.Code))
        .ReverseMap();
});

You need Custom Value Resolvers : 您需要自定义值解析器

CreateMap<Models.Account, AccountDto>()
    .ForMember(dest => dest.PurchaseVatCode,
        opt => opt.MapFrom(src => new VatDto
        {
            Code = src.PurchaseVatCode,
            Description = src.PurchaseVatDescription,
            Percentage = src.PurchaseVatPercentage
        }));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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