自动映射使用自定义逻辑映射属性的更好方法

时间:2016-11-03 14:12:05

标签: c# .net mapping automapper

我有一个名为Supplier的简单类,它有联系人,联系人可以有地址。现在我们在该联系人中只使用了1个联系人和1个地址(第1行到第4行)。将来我们可能会使用具有多个地址的多个联系人。下面是我的班级

public class SupplierDto
    {

        public string Name { get; set; }
        public string Alias { get; set; }
        public int? SupplierTypeId { get; set; }
        public int? WebclicsManufacturerId { get; set; }
        public string SAPCode { get; set; }

        public string Line1 { get; set; }
        public string Line2 { get; set; }

        public string Line3 { get; set; }
        public string Line4 { get; set; }
        public int CountryId { get; set; }
        public string PostalCode { get; set; }


        public string ContactName { get; set; }
        public string ContactEmail { get; set; }
        public string ContactTelephone { get; set; }
        public string ContactJobTitle { get; set; }
    }

我的供应商类别有点复杂,所以我试图从供应商映射到DTO,下面是我的映射。

CreateMap<Supplier, SupplierDto>()
                .ForMember(dest => dest.Line1, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line1))
                .ForMember(dest => dest.Line2, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line2))
                .ForMember(dest => dest.Line3, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line3))
                .ForMember(dest => dest.Line4, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line4))
                .ForMember(dest => dest.CountryId, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.CountryId))
                .ForMember(dest => dest.PostalCode, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.PostalCode))
                .ForMember(dest => dest.ContactName, options => options.MapFrom(source => source.SupplierContacts.First().Contact.Name))
                .ForMember(dest => dest.ContactEmail, options => options.MapFrom(source => source.SupplierContacts.First().Contact.Email))
                .ForMember(dest => dest.ContactTelephone, options => options.MapFrom(source => source.SupplierContacts.First().Contact.Telephone))
                .ForMember(dest => dest.ContactJobTitle, options => options.MapFrom(source => source.SupplierContacts.First().Contact.JobTitle));

如您所见,我为每列提供了自定义逻辑。现在问题是如果没有联系人/地址,代码中断因为我正在使用

  

首先()

来自LINQ的

,是否有更好的方法来检查联系人是否存在然后进行映射,如果有地址则继续进行地址映射?

1 个答案:

答案 0 :(得分:1)

只需创建一个ContactDto并将其添加到SupplierDto,然后将所有联系人相关属性移动到ContactDto。

public class ContactDto
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }

    public string Line3 { get; set; }
    public string Line4 { get; set; }
    public int CountryId { get; set; }
    public string PostalCode { get; set; }

    public string ContactName { get; set; }
    public string ContactEmail { get; set; }
    public string ContactTelephone { get; set; }
    public string ContactJobTitle { get; set; }
}

public class SupplierDto
{
    public string Name { get; set; }
    public string Alias { get; set; }
    public int? SupplierTypeId { get; set; }
    public int? WebclicsManufacturerId { get; set; }
    public string SAPCode { get; set; }

    public ContactDto Contact { get; set; }
}

然后映射应该看起来像这样

CreateMap<Supplier, SupplierDto>()
    .ForMember(dest => dest.Contact, options => options.MapFrom(source => source.SupplierContacts.FirstOrDefault()));

如果Contact为null,则AutoMapper不会尝试映射它。如果您希望在Future中支持供应商上的多个联系人,则只需将ContactDto Contact属性更改为List<ContactDto>并删除映射中的.FirstOrDefault()