Правильно ли я использую функцию включения Automapper 2.0? - PullRequest
8 голосов
/ 14 января 2012

Либо нет, либо он не работает ... У меня есть один класс Source, который я хочу сопоставить с несколькими представлениями, которые наследуются друг от друга.

В основном базовый класс - этоDetail, а дочерним классом является Edit или Update, которые используют все те же данные, что и Detail, а также пару других полей для управления своими собственными списками или чем-то еще.

Вот карты, которые я использую:

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>();

Тогда, если я Mapper.Map (тикет), любое из свойств, использующих MapFrom, не будет оценено, они просто получатсясо значениями, которые были бы у них, если бы не было сопоставления множеств.

Так что же здесь не так?

Ответы [ 2 ]

7 голосов
/ 15 января 2012

Как альтернативное решение, если вы не хотите звонить Mapper.Map два раза. Вы можете переместить общие отображения Detail в метод расширения:

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)));
    }
}

И затем используйте этот метод расширения при регистрации картографов Ticket -> Update и Ticket -> Edit:

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();

Тогда вы можете использовать карту как обычно:

Ticket ticket = new Ticket();    
var edit = Mapper.Map<Ticket, Edit>(ticket);
var update = Mapper.Map<Ticket, Update>(ticket); 
5 голосов
/ 15 января 2012

Правильно ли я использую функцию включения Automapper 2.0?

Нет - при использовании .Include AutoMapper ожидает, что целевые классы находятся в иерархии, аналогичной исходным классам (это обсуждается далее здесь ). Другими словами, если бы вы отображали разные подклассы от Ticket до Detail, Update и Edit, Include было бы уместно.

Это не кажется полезным в вашем случае. Я бы порекомендовал использовать перегрузку .Map, которая принимает существующий объект и модифицирует его. Таким образом, вам нужно только определить отображение для базового типа:

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