AutoMapper自定义 - 将字符串映射到DTO

时间:2018-04-06 11:04:31

标签: c# automapper

我有以下型号:

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

我想以平面模式读取数据,然后将其映射到AccountDto。 我尝试使用以下行配置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);

但上述尝试都没有奏效,我仍然无法映射PurchaseVatCode

我收到以下错误:

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

任何人都可以帮忙解决这个问题吗? 提前谢谢!

2 个答案:

答案 0 :(得分:2)

所有困难都源于AccountDto属性名称PurchaseVatCodeSalesVatCode的错误选择。为了让AutoMapper正确地展平名称,我们需要删除Code后缀。

问题是Account具有相同名称但类型不同的属性。所以我们不能使用RecognizeAlias重命名它们,因为它也会重命名目标属性。

源和目标分开的唯一方法是指定前缀/后缀。但是,如果我们使用RecognizeSuffix("Code")从源CodePurchaseVatCode中删除SalesVatCode,那么不幸的是,这也会影响VatDto.Code属性(这可能会被考虑当前的AutoMapper缺陷)。

在这种情况下,您可以做的最好的事情是使用后者来完成大部分工作并明确映射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();
});

答案 1 :(得分:1)

您需要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
        }));