Either I'm not, or it isn't working... I have a single Source class that I want to map to multiple views that inherit from each other.
Basically the base class is the Detail, and the child class is Edit or Update which use all the same data as Detail, plus a couple other fields to manage their own lists or whatever.
Here are the maps I'm using:
Mapper.CreateMap<Ticket, Detail>()
.Include<Ticket, Update>()
.Include<Ticket, Edit>()
.ForMember(dest => dest.Priority, opt => opt.MapFrom(src => src.Priority.Code))
.ForMember(dest => dest.TicketID, opt => opt.MapFrom(src => src.ID))
.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.StatusCode))
.ForMember(dest => dest.Category, opt => opt.MapFrom(src => src.ProblemCategoryCode))
.ForMember(dest => dest.crmBusCode, opt => opt.MapFrom(src => src.Company.crmBusCode))
.ForMember(dest => dest.TeamMembers, opt => opt.MapFrom(src => src.Schedules.Where(s => s.CompleteTime == null)));
Mapper.CreateMap<Ticket, Update>()
.ForMember(m => m.Schedules, opt => opt.MapFrom(t => t.Schedules.Where(s => s.EmployeeID == Util.CurrentUserID() && s.CompleteTime == null)));
Mapper.CreateMap<Ticket, Edit>();
Then if I Mapper.Map(ticket) any of the properties that use MapFrom don't get evaluated, they just end up with the values they'd have had if there was no set mapping.
So what's wrong here?
As an alternative solution if you don't want to call Mapper.Map
two times. You can move the common mappings of Detail
into an extension method:
public static class MappingExtensions
{
public static IMappingExpression<Ticket, TDest> MapDetailProperties<TDest>(
this IMappingExpression<Ticket, TDest> mapBase) where TDest : Detail
{
return mapBase
.ForMember(dest => dest.Priority,
opt => opt.MapFrom(src => src.Priority.Code))
///....
.ForMember(dest => dest.TeamMembers,
opt => opt.MapFrom(src => src
.Schedules.Where(s => s.CompleteTime == null)));
}
}
And then use that extension method when registering the Ticket -> Update
and Ticket -> Edit
mappers:
Mapper.CreateMap<Ticket, Update>()
.MapDetailProperties()
.ForMember(m => m.Schedules, opt => opt.MapFrom(t => t.Schedules
.Where(s => s.EmployeeID == Util.CurrentUserID() &&
s.CompleteTime == null)));
Mapper.CreateMap<Ticket, Edit>()
.MapDetailProperties();
Then you can use Map normally:
Ticket ticket = new Ticket();
var edit = Mapper.Map<Ticket, Edit>(ticket);
var update = Mapper.Map<Ticket, Update>(ticket);
Am I using Automapper 2.0's Include functionality correctly?
No--When you use .Include
, AutoMapper expects that the destination classes are in a similar hierarchy as the source classes (This is discussed further here). In other words, if you were mapping to different subclasses of Ticket
to Detail
, Update
and Edit
, Include
would be appropriate.
This doesn't seem helpful in your case. I would recommend using the overload of .Map
that takes an existing object and modifies it. That way, you only have to define a mapping for the base type:
Ticket ticket = new Ticket();
Edit edit = new Edit();
Mapper.Map<Ticket, Detail>(ticket, edit);
// Edit has now been automapped using the base mapping.
Mapper.Map<Ticket, Edit>(ticket, edit);
// The properties unique to Edit have now been mapped.