AutoMapper entity mapping
I have a db object that stores order addresses like this ...
And I have 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 an EF object with the above classes based on the AddressType column. Can someone explain to me how to do this?
UPDATE
I want to go to OR.DeliveryAddress
if addressType is "Shipping" and OR.InvoiceAddress
if addressType is "Invoice"
So far I could do it, but I don't know how to apply the condition at 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 a scenario I could come up with for my problem ...
source to share
You can create a client object for an object. Also, you don't need to specify every property with ForMember
, because if the difference is only uppercase / lowercase (if only for PersonName
), the default AutoMapper
is case insensitive when matching the property name.
Create a custom mapper for the 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 handler.
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>();
Using.
var orderAddressDto = Mapper.Map<object>(orderAddress);
The actual type orderAddressDto
will be based on addressType
. If you have an interface or base class for OR.DeliveryAddress
and OR.InvoiceAddress
that will be more powerful. Then replace the object type with interface / base class.
source to share
You can try to look at ResolveUsing
Semi-pseudocode as I don't know what your whole domain model looks like:
Mapper.CreateMap<OrderObject, OrderDto>()
.ForMember(x => x.Address, opt => opt.ResolveUsing(oo => oo.Type == Invoice ? oo.InvoiceAddress : oo.DeliveryAddress));
I am assuming you have a real Order object that you are trying to do in "OrderDto" that contains only one address field.
source to share