Zignoruj ​​mapowanie jednej właściwości za pomocą Automapper


285

Używam Automapper i mam następujący scenariusz: Klasa OrderModel ma właściwość o nazwie „ProductName”, która nie znajduje się w bazie danych. Więc kiedy próbuję wykonać mapowanie za pomocą:

Mapper.CreateMap<OrderModel, Orders>(); 

Generuje wyjątek:

„Następujące 1 właściwości w Project.ViewModels.OrderModel nie są odwzorowane:„ ProductName ”

Przeczytałem na Wiki AutoMapper dla Projekcji odwrotną wielkość liter (dodatkowy atrybut znajduje się w miejscu docelowym, a nie w źródle, które tak naprawdę jest moim przypadkiem)

Jak mogę uniknąć automatycznego mapowania, aby zmapować tę właściwość?


7
Automapper nie działa w ten sposób. Dotyczy to tylko właściwości obiektu docelowego. Src może zawierać 100 dodatkowych właściwości - Automapper mapuje tylko właściwości dest. Musi istnieć coś innego, co powoduje wyjątek mapowania. Czy możesz opublikować kod, który nie działa?
PatrickSteele,

Robi to, o co prosisz automatycznie. Opublikuj kod, aby wyjaśnić
BeRecursive

Zapoznaj się z następującymi postami, które mogą ci pomóc stackoverflow.com/questions/4456519/… stackoverflow.com/questions/4052579/...
Divi

3
@Patrick AutoMapper wykonuje kilka sztuczek, analizując nazwy metod / właściwości. Możliwe, że w źródle znajduje się właściwość, która jest nieumyślnie mapowana, nawet jeśli nie ma dokładnego dopasowania w miejscu docelowym. Właśnie dlatego istnieje ForSourceMember (... Ignore ()), aby temu zapobiec, gdy się pojawi.
AaronLS,

Odpowiedzi:


478

Od Jimmy'ego Bogarda: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

Jest to jeden z komentarzy na jego blogu .


13
Ponadto, CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());mogą być przydatne
stackoverfloweth

5
@stackoverfloweth Czy nie chodziło CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())?
poniedziałek

12
Ignore zostało zastąpione przez DoNotValidate w ForSourceMember: github.com/AutoMapper/AutoMapper/blob/master/docs/…
Jamie

@Jamie @monty - zacząłem aktualizować to: twój komentarz, ale wygląda na to, że zmiana składni dotyczy tylko przypadku projekcji (gdzie właściwość source musi zostać zignorowana). Prośba OP ma zignorować właściwość docelową, więc Ignore()pozostaje poprawna składnia. Wynika to z faktu, że zmiany składni Ignoredokonano w ISourceMemberConfigurationExpressioninterfejsie, ale nie w IMemberConfigurationExpression`3interfejsie rozłącznym .
smartcaveman

2
@Franva ForMember () to tak naprawdę „ForDestinationMember ()”
rvnlord

243

Być może jestem trochę perfekcjonistą; Naprawdę nie lubię składni ForMember (..., x => x.Ignore ()). To drobiazg, ale ma dla mnie znaczenie. Napisałem tę metodę rozszerzenia, aby była nieco ładniejsza:

public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> map,
    Expression<Func<TDestination, object>> selector)
{
    map.ForMember(selector, config => config.Ignore());
    return map;
}

Można go używać w następujący sposób:

Mapper.CreateMap<JsonRecord, DatabaseRecord>()
        .Ignore(record => record.Field)
        .Ignore(record => record.AnotherField)
        .Ignore(record => record.Etc);

Możesz również przepisać go do pracy params, ale nie podoba mi się wygląd metody z dużą ilością lambda.


6
Wiem, że wykracza to poza początkowe pytanie, ale bardzo podoba mi się ta odpowiedź, jest czysta, bardzo łatwa do odczytania i natychmiast zrozumiana, a także łatwa do ponownego użycia
Lski,

Odnośnie params: Możesz zwrócić tablicę selektorów z wnętrza jednej lambda, a następnie odwzorować każdy selektor za pomocą foreachlub Select()Być może nie mniej niechlujnie wyglądający.
jpaugh

dzięki @Steve Rukuts, za każdego, kto szuka metody rozszerzenia do ignorowania członków źródła, możesz użyć tego publicznego statycznego IMappingExpression <TSource, TDestination> IgnoreSourceValidation <TSource, TDestination> (ta mapa IMappingExpression <TSource, TDestination> mapa, wyrażenie <Func <TSource , obiekt >> selektor) {map.ForSourceMember (selektor, config => config.DoNotValidate ()); mapa powrotna; }
Jason Dias,

79

Możesz to zrobić:

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());

Czy automapper ma rozszerzenie ForSourceMember?
Wykorzystany 1

Robię to obecnie, ale idealnie byłoby NIE tworzyć wszystkich Ignoruj ​​...: /
Tom Stickel

wiesz, czy istnieje sposób na zignorowanie podczas tworzenia mapowania, a nie podczas tworzenia mapy?
Sam, jestem, mówi Przywróć Monikę


3
W przypadku scenariusza podanego w pytaniu powinna to być zaakceptowana odpowiedź. Obecna akceptowana odpowiedź ignoruje mapowanie właściwości w obiekcie docelowym. To pytanie dotyczy ignorowania odwzorowań w obiekcie źródłowym.
Rob S.

28

Tylko dla każdego, kto próbuje to zrobić automatycznie, możesz użyć tej metody rozszerzenia, aby zignorować nieistniejące właściwości typu docelowego:

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof(TSource);
    var destinationType = typeof(TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
        && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

stosować w następujący sposób:

Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();

dzięki Can Gencer za wskazówkę :)

źródło: http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/



1
Nie działa to podczas wstrzykiwania IMappera. Mapper.GetAllTypeMaps nie istnieje w najnowszej wersji AutoMapper. Ponadto, kiedy konfiguruję moje mapy w AutoMapper.Profile, a następnie wstrzykuję IMapper, otrzymałem ten wyjątek: „Maper nie został zainicjowany. Wywołanie Inicjuj z odpowiednią konfiguracją. Jeśli próbujesz użyć instancji mapera przez kontener lub w inny sposób, upewnij się, że nie wykonuj żadnych wywołań do statycznych metod Mapper.Map, a jeśli używasz metod rozszerzenia ProjectTo lub UseAsDataSource, upewnij się, że przekazałeś odpowiednią instancję IConfigurationProvider. ”
Ristogod,

Właśnie dostaję 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie

2
@Bassie Użyj Mapper.Configuration.GetAllTypeMaps() źródła
Mike Bovenlander,

28

Teraz jest (AutoMapper 2.0) IgnoreMapatrybut, którego zamierzam użyć zamiast płynnej składni, która jest nieco ciężka IMHO.


35
Jednak atrybut ignorowania powoduje wyciek automatycznego mapowania przez twoją aplikację.
Phill

11
AutoMapper to jedna rzecz, której nie mam nic przeciwko wyciekaniu wszędzie. ;)
Paweł Krakowiak,

4
Zawsze możesz rozważyć wyprowadzenie IgnoreMapAttribute.
Alapago

1
Jest to dobry sposób na zignorowanie podstawowej właściwości dziedziczonej po wielu obiektach. Oszczędza konieczności ignorowania go w każdej konfiguracji mapowania.
Chase Florell

23

Podczas mapowania modelu widoku z powrotem na model domeny znacznie łatwiej jest po prostu sprawdzić źródłową listę członków niż docelową listę członków

Mapper.CreateMap<OrderModel, Orders>(MemberList.Source); 

Teraz sprawdzanie poprawności mapowania nie kończy się niepowodzeniem, wymagając innej Ignore(), za każdym razem, gdy dodam właściwość do mojej klasy domeny.


7
Właśnie tego szukałem, tak przydatnego, gdy modyfikuję tylko podzbiór właściwości obiektów domeny z dużo prostszego DTO.
Adam Tolley,

5
To jest odpowiedź dla dzieci, sprawiają, że urzędnik więc początkujący nie będą mylić
Piotr M

0

Można użyć IgnoreAttribute we właściwości, którą należy zignorować


2
Jest [IgnoreMap]odIgnoreMapAttribute
fiorebat

-5

Witam wszystkich Proszę użyć tego działa dobrze ... do automatycznego mapowania używać wielu. Dla Członka w C #

        if (promotionCode.Any())
        {
            Mapper.Reset();
            Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
                .ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
                .ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
                .ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
                .ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
                .ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate))); 
            var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
            return userPromotionModel;
        }
        return null;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.