简体   繁体   中英

AutoMapper Conditional Entity Mapping

I have a db entity which stores the Order Addresses like this...

在此输入图像描述

And I have the BLL classes like this...

public class DeliveryAddress
{
    public string Id { get; set; }
    public string PersonyName { get; set; }
    public string CompanyName { get; set; }
    public List<string> AddressLines { get; set; }
    public string Zip { get; set; }
    public string City { get; set; }
    public string CountryCode { get; set; }
}

and another class like this...

public class InvoiceAddress
{
    public string Id { get; set; }
    public string PersonyName { get; set; }
    public string CompanyName { get; set; }
    public List<string> AddressLines { get; set; }
    public string Zip { get; set; }
    public string City { get; set; }
    public string CountryCode { get; set; }
}

and I want to map the EF entity to the above classes on the basis of AddressType column. Can anybody explain me how to do that ?

UPDATE

I want to map to OR.DeliveryAddress if the addressType is "Delivery" and to OR.InvoiceAddress if the addressType is "Invoice"

So far, I have been able to do this, but I don't know how to apply condition on the entity mapping level...

Mapper.CreateMap<OrderAddress, OR.DeliveryAddress>()
       .ForMember(d => d.City, o => o.MapFrom(s => s.city))
       .ForMember(d => d.CompanyName, o => o.UseValue(string.Empty))
       .ForMember(d => d.CountryCode, o => o.MapFrom(s => s.countryCode))
       .ForMember(d => d.Id, o => o.MapFrom(s => s.id))
       .ForMember(d => d.PersonyName, o => o.MapFrom(s => s.name))
       .ForMember(d => d.Zip, o => o.MapFrom(s => s.zip));

UPDATE 2

After discussion with @Yuliam Here is the Fiddle that I could come up with for my problem...

You can create a customer mapper to object. And also you don't have to specify each property using ForMember because if the difference is only upper case / lower case (unless for PersonName ), by default AutoMapper is case insensitive when mapping the property name.

Create a custom mapper to object.

public class AddressConverter : ITypeConverter<OrderAddress, object>
{
    public object Convert(ResolutionContext context)
    {
        var o = context.SourceValue as OrderAddress;
        if (o == null) return null;

        if (o.addressType == "Delivery") return Mapper.Map<OR.DeliveryAddress>(o);
        if (o.addressType == "Invoice") return Mapper.Map<OR.InvoiceAddress>(o);
        return null;
    }
}

Then define the mapper.

Mapper.CreateMap<OrderAddress, OR.DeliveryAddress>()
    .ForMember(d => d.PersonyName, o => o.MapFrom(s => s.name));
Mapper.CreateMap<OrderAddress, OR.InvoiceAddress>()
    .ForMember(d => d.PersonyName, o => o.MapFrom(s => s.name));
Mapper.CreateMap<OrderAddress, object>().ConvertUsing<AddressConverter>();

Usage.

var orderAddressDto = Mapper.Map<object>(orderAddress);

The actual orderAddressDto type will be based on the addressType . If you have an interface or base class for OR.DeliveryAddress and OR.InvoiceAddress that would be more strongly type. Then replace the object type with the interface / base class.

You may want to try taking a look at ResolveUsing

Semi-pseudo code, as I don't know what your entire Domain Model looks like:

Mapper.CreateMap<OrderObject, OrderDto>()
    .ForMember(x => x.Address, opt => opt.ResolveUsing(oo => oo.Type == Invoice ? oo.InvoiceAddress : oo.DeliveryAddress));

I'm assuming here that you have an actual Order entity, which you're trying to make to an 'OrderDto' which only contains one address field.

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