Automapper
Automapper
Mapper.Initialize(cfg =>
cfg.CreateMap<OrderLine, OrderLineDTO>()
.ForMember(dto => dto.Item, conf => conf.MapFrom(ol => ol.Item.Name)));
Null values
Composition:
Mapper.CreateMap<doctor, healthcareprofessional="">()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => string.Join(" ", src.Title, src.FirstName,
src.LastName)));
If field names do not match, you need to specify them. You can define the reverse map.
CreateMap<ViewModels.Base, Models.Base>()
.ForMember(dest => dest.BaseId, opts => opts.MapFrom(src => src.BaseId))
.ForMember(dest => dest.UserId, opts => opts.MapFrom(src => src.UserId))
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.Name));
CreateMap<ViewModels.Base, Models.Base>().ReverseMap();
CreateMap<IbisAssetAccDetail, AddressBodyDto>()
.ForMember(t => t.City, o => o.MapFrom(s => s.City))
.ForAllOtherMembers(t => t.Ignore());
CreateMap<IbisAssetAccDetail, AddressBodyDto>()
.ForMember(x => x.CountryName, o => o.Ignore());
PostProcess
CreateMap<IbisAssetAccDetail, AddressBodyDto>()
.ForMember(x => x.CountryName, o => o.Ignore());
.AfterMap<MapCountryByCultureExpression>();
CreateMap<FnGetHoldingResult, ExportHoldingDto>().AfterMap(
(a, x) =>
{
var resourceValue = ResourceManager.GetString("SecurityMasterType_" + a.SecurityType);
if (!string.IsNullOrEmpty(resourceValue))
x.SecurityType = resourceValue;
});
Reverse
CreateMap<IbisAssetAccDetail, AddressBodyDto>()
.ForMember(t => t.City, o => o.MapFrom(s => s.City)).ReverseMap()
AutoMapper does not know about any mapping from string to int, DateTime or Type. To create maps for these
types, we must supply a custom type converter, and we have three ways of doing so:
Func
cfg.CreateMap<string, int>().ConvertUsing(s => Convert.ToInt32(s));
//Arrange
Mapper.CreateMap<doctor, healthcareprofessional="">()
.ConvertUsing<healthcareprofessionaltypeconverter>();
Mapper.AssertConfigurationIsValid();
//Act
HealthcareProfessional result = Mapper.Map<healthcareprofessional>(source);
//Assert
Assert.IsNotNull(result);
Value Resolvers
Value resolves allow for correct mapping of value types. The source object KitchenCutlery contains a precise breakdown
of the number of knifes and forks in the kitchen, whereas the destination object Kitchen only cares about the sum total of
both. AutoMapper won’t be able to create a convention based mapping here for us, so we use a Value (type) Resolver;
The value resolver, similar to the type converter, takes care of the mapping and returns a result, but notice that it is specific to
the individual property, and not the full object. The following code snippet shows how to use a Value Resolver;
Mapper.CreateMap<kitchencutlery, kitchen="">()
.ForMember(dest => dest.KnifesAndForks, opt => opt.ResolveUsing<kitchenresolver>());
//Act
//Assert
Mapper.AssertConfigurationIsValid();
}
Null Substitution
Think default values. In the event that you want to give a destination object a default value when the source value is null, you
can use AutoMapper’s NullSubstitute feature.
Mapper.CreateMap<doctor, person="">()
.ForMember(dest => dest.Title, opt => opt.NullSubstitute("Dr"));
//Act
Person result = Mapper.Map<person>(source);
//Assert
Assert.AreSame(result.Title, "Dr");
}
AutoMapper doesn't require special support for converting a list or an array of items. As long as I define the element
type mapping, AutoMapper can handle enumerating the list, performing the mapping and returning a new, mapped list.
All of the mappings I've showed so far don't need any changes (or additional mappings defined) to support a collection
of employees:
AutoMapper will also let you define code to run before and after the mapping process. The pre-condition is useful if you
have a property on your source object that you want to use in the mapping, but it has to be loaded or initialized before it
can be used (perhaps loaded from NHibernate). For this type of situation, use the BeforeMap method:
The lambda gets access to both the mapped source object (the first parameter) as well as the destination object (the
second parameter). Likewise, you can define an AfterMap lambda that will be called after AutoMapper has done its job:
Cons
One of the most common architectures for web apps right now is based on passing DataTransferObjects(DTOs) to and
from CRUD services that updates your business/domain entities using tools like AutoMapper and EntityFramework. I
will try to explain why this is a truly horrible approach.
Startup.cs
using AutoMapper;