4

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

Naveed Butt
  • 2,861
  • 6
  • 32
  • 55

2 Answers2

2

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.

Yuliam Chandra
  • 14,494
  • 12
  • 52
  • 67
  • I have `List` in the `Order` entity and when I call `AutoMapper.Map(order);`. Will it work? – Naveed Butt Sep 04 '14 at 07:15
  • @NaveedButt, you can just map the property like this `var result = AutoMapper.Map(order.OrderAddresses);` – Yuliam Chandra Sep 04 '14 at 07:20
  • I used this, but it did not work, so not marking your answer. I am still looking for the answer. I managed to do it using `Linq` queries, i.e., populate the object manually... – Naveed Butt Sep 10 '14 at 08:42
  • @NaveedButt, Did you map the order address directly? or from the order? How did you map it? – Yuliam Chandra Sep 10 '14 at 08:47
  • @NaveedButt, in the question there is no usage of map, just configuration, let me clarify again, did you use `var orderAddressDto = Mapper.Map(orderAddress)` or `var orderDto = Mapper.Map(order)` or `var addressesDto = Mapper.Map(order.OrderAddresses)` or something else ? – Yuliam Chandra Sep 10 '14 at 08:56
  • I used this... `var orderAddressDto = Mapper.Map(orderAddress)` – Naveed Butt Sep 10 '14 at 09:11
  • @NaveedButt, it's working fine [here](https://dotnetfiddle.net/PKR7Lf), probably something missing at your side that is not properly configured or wrong usage – Yuliam Chandra Sep 10 '14 at 09:27
  • I am sorry, if I am unable to explain my problem, but this is my problem: https://dotnetfiddle.net/X93DEM Hope you can help me now... – Naveed Butt Sep 10 '14 at 09:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60951/discussion-between-yuliam-chandra-and-naveed-butt). – Yuliam Chandra Sep 10 '14 at 09:45
0

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.

t0yk4t
  • 854
  • 8
  • 10
  • There is a `List` in the Order entity plus. This is the way to convert the Entity to DTO. What would be the way to convert the DTO back to Entity? I think I would have to use Yuliam's method for that, right ? – Naveed Butt Sep 04 '14 at 07:54