Как игнорировать все элементы назначения, кроме тех, которые отображаются?
Есть ли способ сделать это? У нас есть SummaryDto, который отображает три разных типа, и когда мы создаем карту для каждого типа, реквизиты, которые не отображаются, вызывают ошибку. В сводке dto имеется около 35 атрибутов. Использовать опцию Ignore() для каждого из них - слишком большая проблема. Есть глобальное игнорирование? Что-то вроде
CreateMap<Source,Target>()
.IgnoreAllUnmapped();
Ответы
Ответ 1
Это работает для меня:
public static class MappingExpressionExtensions
{
public static IMappingExpression<TSource, TDest> IgnoreAllUnmapped<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
{
expression.ForAllMembers(opt => opt.Ignore());
return expression;
}
}
Поскольку ForAllMembers
возвращает void
, вызов ForAllMembers(o => o.Ignore())
без этого метода расширения не будет работать. Мы хотим сохранить выражение отображения доступным для последующего отображения:
CreateMap<Source, Destination>()
.IgnoreAllUnmapped()
.ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
.ForMember(d => d.Value, o => o.MapFrom(s => s.Id));
Ответ 2
Я слишком долго боролся с этим, или, по крайней мере, проблема, подобная этому. У меня был класс с множеством свойств (около 30), и я только хотел отобразить около 4 из них. Кажется сумасшедшим добавить 26 игнорируемых утверждений (особенно, когда это означает, что будущие изменения в классе означают необходимость их обновления!)
Наконец-то я обнаружил, что могу сказать AutoMapper игнорировать все, а затем явно добавить те, которые мне нужны.
// Create a map, store a reference to it in a local variable
var map = CreateMap<Source,Target>();
// Ignore all members
map.ForAllMembers(opt => opt.Ignore());
// Add mapping for P1
map.ForMember(dest => dest.P1, opt => opt.MapFrom( src => src.P1));
// Add other mappings...
map.ForMember(dest => dest.P2, opt => opt.MapFrom( src => src.P2));
map.ForMember(dest => dest.P3, opt => opt.MapFrom( src => src.P3));
map.ForMember(dest => dest.P4, opt => opt.MapFrom( src => src.P4));
Вам будет прощено думать, что вы можете просто сделать это (но не потому, что он не будет компилироваться):
// This won't compile
CreateMap<Source,Target>()
.ForAllMembers(opt => opt.Ignore())
.ForMember(dest => dest.P1, opt => opt.MapFrom( src => src.P1));
Причина, по которой это не работает, заключается в том, что метод ForAllMembers() не поддерживает свободный стиль цепочки (по крайней мере, в текущей версии 2.0).
Хорошей новостью является то, что версия без цепочки действительно работает. Разумеется, одно из предостережений заключается в том, что вам нужно явно указать AutoMapper, какие члены должны отображаться. Я еще не нашел простой способ иметь его в обоих направлениях, чтобы вы все еще могли использовать подразумеваемые сопоставления и игнорировать разбитые.
Ответ 3
Чтобы избежать явного указания отображаемых свойств, вы можете использовать IgnoreAllNonExisting. Он игнорирует любые свойства назначения, которые не имеют отображаемых свойств источника.
Ответ 4
Попробуйте использовать .ConvertUsing()
в вашем случае, например.
CreateMap<Source,Target>()
.ConvertUsing(converter=> new Target(){
P1 = converter.P1,
....
});
Итак, вы можете описать все свойства, которые вы хотите иметь в своем объекте, другие будут проигнорированы.
Ответ 5
Метод расширения, который позволяет свободно использовать синтаксис метода ForAllMembers:
public static IMappingExpression<TSource, TDestination> IgnoreAllMembers<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> expression
)
{
expression.ForAllMembers(opt => opt.Ignore());
return expression;
}
Использование:
Вызов IgnoreAllMembers должен быть до вызова ForMember.
CreateMap<LocationRevision, Dto.LocationAddressMap>()
.IgnoreAllMembers()
.ForMember(m => m.LocationId, opt => opt.MapFrom(src => src.Id))
;