My class XmlOrder contains the two properties
public class XmlOrder
{
public OrderType OrderType { get; set; }
public object Item { get; set; }
}
If OrderType equals OrderType.Service, Item will be of type XmlTransportElement. If it is OrderType.Transport, it will be of type XmlTransport. XmlTransport has the following two properties:
public class XmlTransport
{
public XmlTransportElement Delivery { get; set; }
public XmlTransportElement Pickup { get; set; }
}
XmlOrder needs to be mapped to Order which looks like this:
public class Order : IOrder
{
public ITransportElement[] TransportElements { get; set; }
}
This array will either have one or two entries based on the logic above.
In my sample project, I've written this using the latest AutoMapper version, and it works perfectly:
public class OrderProfile : Profile
{
public OrderProfile()
{
// Mapping for XmlOrder to IOrder
CreateMap<XmlOrder, IOrder>()
.ConstructUsing(src => new Order())
.ForMember(dest => dest.TransportElements, opt => opt.MapFrom((src, dest, _, context) =>
src.Item is XmlTransport transport
? new[]
{
transport.Delivery != null ? context.Mapper.Map<TransportElement>(transport.Delivery) : null,
transport.Pickup != null ? context.Mapper.Map<TransportElement>(transport.Pickup) : null
}
: new[] { context.Mapper.Map<TransportElement>((XmlTransportElement)src.Item) }
));
// Mapping for XmlTransportElement to TransportElement
CreateMap<XmlTransportElement, TransportElement>()
// additional logic
}
}
The problem is, I need to implement this in a legacy application using AutoMapper 6.1.1. The above code doesn't work because .MapFrom cannot be used like this in older versions. I've been going in circles for two days and tried various approaches using .ConvertUsing and .ResolveUsing in combination with a custom converter but always get NullReferenceExceptions or other errors.
The latest approach I've tried was this one, which throws an AutoMapperMappingException:
CreateMap<XmlOrder, IOrder>()
.ForMember(dest => dest.TransportElements, opt => opt.ResolveUsing(src =>
{
var transport = src.Item as Transport;
if (transport != null)
{
return new[]
{
transport.Delivery != null ? Mapper.Map<TransportElement>(transport.Delivery) : null,
transport.Pickup != null ? Mapper.Map<TransportElement>(transport.Pickup) : null
};
}
return new[] { Mapper.Map<TransportElement>((XmlTransportElement)src.Item) };
}))
.ConstructUsing(src => new Order());
Any help is appreciated. AI hasn't been helpful at all and keeps suggesting things that don't work with this particular AutoMapper version.
TransportModel? What are the actual classes and how was AutoMapper configured? The 6.1.1 code mixes up profiles and the static mapper. That static mapper needs to be configured forTransportElementand whatevertransport.Deliveryis.AutoMapper works because it enforces a convention. It assumes that your destination types are a subset of the source type. It assumes that everything on your destination type is meant to be mapped. It assumes that the destination member names follow the exact name of the source type. It assumes that you want to flatten complex models into simple onesDeliveryis a property of typeTransportElementas explained above. Mapping 'TransportElement' is straight forward as it only consists of a bunch of strings and other types that already have mapping profiles. My only issue here is how to deal with 'Item' being of type 'object' in the 6.1.1 version.