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?


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 .


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.


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

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


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/



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.


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.


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


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;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.