Naveed Butt
Naveed Butt

Reputation: 2901

AutoMapper Conditional Entity Mapping

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

enter image description here

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...

Upvotes: 4

Views: 2754

Answers (2)

t0yk4t
t0yk4t

Reputation: 892

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.

Upvotes: 0

Yuliam Chandra
Yuliam Chandra

Reputation: 14640

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.

Upvotes: 2

Related Questions