Ignorieren Sie die Zuordnung einer Eigenschaft zu Automapper

285

Ich verwende Automapper und habe das folgende Szenario: Class OrderModel hat eine Eigenschaft namens 'ProductName', die nicht in der Datenbank enthalten ist. Wenn ich also versuche, das Mapping durchzuführen mit:

Mapper.CreateMap<OrderModel, Orders>(); 

Es wird eine Ausnahme generiert:

"Die folgenden 1 Eigenschaften von Project.ViewModels.OrderModel sind nicht zugeordnet: 'ProductName'

Ich habe im AutoMapper-Wiki für Projektionen den umgekehrten Fall gelesen (das zusätzliche Attribut befindet sich am Ziel, nicht in der Quelle, die eigentlich mein Fall ist).

Wie kann ich vermeiden, dass Automapper die Zuordnung dieser Eigenschaft vornimmt?

Msam85
quelle
7
Automapper funktioniert so nicht. Es geht nur um Eigenschaften des Zielobjekts. Der src kann 100 zusätzliche Eigenschaften enthalten - Automapper ordnet nur die dest-Eigenschaften zu. Es muss etwas anderes geben, das die Zuordnungsausnahme verursacht. Können Sie einen Code veröffentlichen, der zeigt, was nicht funktioniert?
PatrickSteele
Es macht das, was Sie fragen, automatisch.
Veröffentlichen Sie
Werfen Sie einen Blick auf die folgenden Beiträge, diese könnten Ihnen helfen, stackoverflow.com/questions/4456519/… stackoverflow.com/questions/4052579/…
Divi
3
@Patrick AutoMapper führt einige Tricks mit der Analyse von Methoden- / Eigenschaftsnamen aus. Es ist möglich, dass die Eigenschaft eine Eigenschaft enthält, die unbeabsichtigt zugeordnet wird, auch wenn das Ziel nicht genau übereinstimmt. Aus diesem Grund gibt es ein ForSourceMember (... Ignore ()), um dies zu verhindern, wenn es auftritt.
AaronLS

Antworten:

477

Von Jimmy Bogard: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

Es ist in einem der Kommentare in seinem Blog .

Smartcaveman
quelle
13
Auch CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());könnte nützlich sein
Stackoverfloweth
5
@stackoverfloweth Meinst du nicht : CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())?
Montag,
12
Ignorieren wurde in ForSourceMember durch DoNotValidate ersetzt: github.com/AutoMapper/AutoMapper/blob/master/docs/…
Jamie
@Jamie @monty - Ich habe begonnen, diesen Kommentar zu aktualisieren: Ihr Kommentar, aber es sieht so aus, als ob die Syntaxänderung nur den Projektionsfall betrifft (bei dem die Quelleigenschaft ignoriert werden muss). Die Anforderung des OP besteht darin, eine Zieleigenschaft zu ignorieren, sodass Ignore()die korrekte Syntax erhalten bleibt. Dies liegt daran, dass die Syntaxänderung für Ignoreauf der ISourceMemberConfigurationExpressionSchnittstelle vorgenommen wurde, nicht jedoch auf der disjunkten IMemberConfigurationExpression`3Schnittstelle.
Smartcaveman
2
@Franva ForMember () ist eigentlich "ForDestinationMember ()"
rvnlord
243

Ich bin vielleicht ein bisschen ein Perfektionist; Ich mag die ForMember (..., x => x.Ignore ()) - Syntax nicht wirklich. Es ist eine kleine Sache, aber es ist mir wichtig. Ich habe diese Erweiterungsmethode geschrieben, um sie ein bisschen schöner zu machen:

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

Es kann wie folgt verwendet werden:

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

Sie könnten es auch umschreiben, um damit zu arbeiten params, aber ich mag das Aussehen einer Methode mit vielen Lambdas nicht.

Steve Rukuts
quelle
6
Ich weiß, dass dies über die ursprüngliche Frage hinausgeht, aber ich mag diese Antwort wirklich, sie ist sauber, sehr leicht zu lesen und sofort zu verstehen und leicht wiederzuverwenden
Lski
In Bezug auf params: Sie könnten eine Reihe von Selektoren aus einem einzelnen Lambda zurückgeben und dann jeden Selektor mit foreachoder Select()vielleicht nicht weniger chaotisch abbilden .
Jpaugh
Vielen Dank an @Steve Rukuts. Für alle, die nach einer Erweiterungsmethode zum Ignorieren von Quellmitgliedern suchen, können Sie diese öffentliche statische IMappingExpression <TSource, TDestination> IgnoreSourceValidation <TSource, TDestination> (diese IMappingExpression <TSource, TDestination> -Karte, Expression <Func <TSource) verwenden , Objekt >> Selektor) {map.ForSourceMember (Selektor, config => config.DoNotValidate ()); Karte zurückgeben; }
Jason Dias
79

Du kannst das:

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());
Richard
quelle
Hat Automapper eine ForSourceMember-Erweiterung?
Eingelöst1
Ich mache das momentan, aber es wäre ideal, NICHT all diese Ignorieren zu müssen ...: /
Tom Stickel
Wissen Sie, ob es eine Möglichkeit gibt, diese zu ignorieren, wenn Sie das Mapping tatsächlich durchführen, und nicht, wenn Sie das Map erstellen?
Sam, ich bin, sagt Reinstate Monica
Zu Ihrer
Information
3
Für das in der Frage angegebene Szenario sollte dies die akzeptierte Antwort sein. Die aktuell akzeptierte Antwort ignoriert die Zuordnung von Eigenschaften im Zielobjekt. Bei dieser Frage geht es darum, Zuordnungen im Quellobjekt zu ignorieren.
Rob S.
28

Nur für alle, die dies automatisch versuchen, können Sie diese Erweiterungsmethode verwenden, um nicht vorhandene Eigenschaften des Zieltyps zu ignorieren:

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

wie folgt zu verwenden:

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

danke an Can Gencer für den Tipp :)

Quelle: http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/

Stéphane
quelle
3
Zu Ihrer
Information
1
Dies funktioniert beim Injizieren von IMapper nicht. Mapper.GetAllTypeMaps ist in der neuesten Version von AutoMapper nicht vorhanden. Wenn ich meine Maps in einem AutoMapper.Profile einrichte und anschließend IMapper injiziere, wird die Ausnahme "Mapper nicht initialisiert. Rufen Sie Initialize mit der entsprechenden Konfiguration auf. Wenn Sie versuchen, Mapper-Instanzen über einen Container oder auf andere Weise zu verwenden, stellen Sie dies sicher Rufen Sie die statischen Mapper.Map-Methoden nicht auf. Wenn Sie die Erweiterungsmethoden ProjectTo oder UseAsDataSource verwenden, stellen Sie sicher, dass Sie die entsprechende IConfigurationProvider-Instanz übergeben. "
Ristogod
Ich bekomme gerade 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie
2
@ Bassie Mapper.Configuration.GetAllTypeMaps() Quelle verwenden
Mike Bovenlander
28

Es gibt jetzt (AutoMapper 2.0) ein IgnoreMapAttribut, das ich anstelle der fließenden Syntax verwenden werde, die meiner Meinung nach etwas schwer ist.

Guillaume
quelle
35
Das Attribut "Ignorieren" führt jedoch zu einem automatischen Mapper in Ihrer Anwendung.
Phill
11
AutoMapper ist eine Sache, die mir nichts ausmacht, überall zu lecken. ;)
Pawel Krakowiak
4
Sie können immer überlegen, abzuleiten IgnoreMapAttribute.
Alapago
1
Dies ist eine gute Möglichkeit, eine Basiseigenschaft zu ignorieren, die von vielen Objekten geerbt wird. Spart, dass es nicht in jeder Mapping-Konfiguration ignoriert werden muss.
Chase Florell
23

Wenn Sie ein Ansichtsmodell wieder einem Domänenmodell zuordnen, kann es viel sauberer sein, einfach die Quellmitgliedsliste und nicht die Zielmitgliedsliste zu überprüfen

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

Jetzt schlägt meine Zuordnungsüberprüfung nicht fehl und erfordert Ignore()jedes Mal eine andere , wenn ich meiner Domänenklasse eine Eigenschaft hinzufüge.

Loren Paulsen
quelle
7
Dies ist das, wonach ich gesucht habe, so nützlich, wenn ich nur eine Teilmenge der Eigenschaften von Domänenobjekten aus einem viel einfacheren DTO heraus ändere.
Adam Tolley
5
Dies ist die Antwort Kinder, machen Sie das offiziell, damit Neulinge nicht verwirrt werden
Piotr M
0

Könnte IgnoreAttribute für die Eigenschaft verwenden, die ignoriert werden muss

Naresh
quelle
2
Es ist [IgnoreMap]vonIgnoreMapAttribute
Fiorebat
-5

Hallo an alle, bitte benutze dies, es funktioniert gut ... für Auto Mapper benutze mehrere .ForMember in 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;
ravikant sonare
quelle