2012-09-04 4 views
6

So konfigurieren Sie die AutoMapper-Zuordnung, wenn ich das Verhalten von UseDestinationValue Methode verwenden möchte, aber nur, wenn die Zieleigenschaft nicht null ist.UseDestinationValue nur, wenn die Zieleigenschaft nicht null ist

So etwas:

Mapper.CreateMap<Item, ItemViewModel>() 
    .ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true)) 

EDIT

class ItemDetails { 
    public string Info { get; set; } 
    public string ImportantData { get; set; } // only in Domain, not in ViewModel 
} 

class Item { 
    public ItemDetails Details { get; set; } 
} 

class ItemDetailsViewModel { 
    public string Info { get; set; } 
} 

class ItemViewModel { 
    public ItemDetailsViewModel Details { get; set; } 
} 

Jetzt Beispiel für die Nutzung. Ich habe eine ItemViewModel Klasse und ich möchte sie der Klasse Item zuordnen.

Mapping-Konfiguration:

Mapper.CreateMap<Item, ItemViewModel>() 
     .ForMember(x => x.Details, _ => _.UseDestinationValue()) 
  1. Erster Fall - Ziel Eigenschaft Item.Details Eigenschaft ist NOT NULL. Jetzt möchte ich AutoMapper diese Zielinstanz von Details Eigenschaft verwenden, weil es nicht null ist.

    Und die Logik sieht wie folgt aus:

    var item = new Item { 
        Details = new Details { 
         Info = "Old text", 
         ImportantData = "Data" 
        } 
    }; 
    
    var itemViewModel = new ItemViewModel { 
        Details = new DetailsViewModel { 
         Info = "New text" 
        } 
    };  
    
    Mapper.Map(itemViewModel, item); 
    

    AutoMapper, wegen des Vorhandenseins von UseDestinationValue, die item.Details Instanz und setzen nur item.Details.Info Eigenschaft verlassen.

  2. Zweiter Fall - Zieleigenschaft Item.Details Eigenschaft ist NULL. Jetzt möchte ich AutoMapper nicht diese Null-Instanz verwenden, sondern neue erstellen. Die Frage ist, wie man das Mapping konfiguriert, um diesen Fall zu berücksichtigen?

    Die Logik sieht wie folgt aus:

    var item = new Item { 
        Details = null 
    }; 
    
    var itemViewModel = new ItemViewModel { 
        Details = new DetailsViewModel { 
         Info = "New text" 
        } 
    }; 
    
    Mapper.Map(itemViewModel, item); 
    

    PROBLEM

    Hier habe ich ein Problem, weil nach der Kartierung, die item.Details Eigenschaft null sein wird (wegen der Verwendung von UseDestinationValue die null ist in dieser Fall).

GRUND

NHibernate, nachdem die Entität aus der Datenbank bekommen, es in einen Proxy stellt. Also die Details Eigenschaft eines geladenen Objekts ist nicht vom Typ: ItemDetails, aber ItemDetailsNHibernateProxy - also muss ich diesen Typ verwenden, wenn ich dieses vorhandene Objekt später in der Datenbank speichern möchte. Aber wenn diese Eigenschaft null ist, dann kann ich keinen Null-Zielwert verwenden, daher sollte Automapper eine neue Instanz erstellen.

Danke, Chris

+0

So tun Sie etwas anderes als UseDestinationValue tun wollen wenn es null ist? – PatrickSteele

+0

Ja, ich möchte etwas anderes tun, wenn die Zieleigenschaft NULL ist. – cryss

+0

Können Sie einen funktionierenden Beispielcode bereitstellen, der Ihnen zeigt, wie Sie die Dinge gemappt werden möchten, im Gegensatz zu dem, was Auotmapper derzeit tut. Ich bekomme einfach nicht, was du verlangst. – PatrickSteele

Antwort

0

Ich denke, die NullSubstitute Option für Sie funktionieren würde.Siehe: http://weblogs.asp.net/psteele/archive/2011/03/18/automapper-handling-null-members.aspx

EDIT

Sieht aus wie Sie ein wenig bedingte Logik auf Ihre Zuordnung für Details hinzufügen können müssen (und überspringen die UseDestinationValue Option):

.ForMember(d => d.Details, 
    o => o.MapFrom(s => s.Details == null ? new ItemDetails() : Mapper.Map<ItemDetailsViewModel, ItemDetails>(s.Details)) 
+1

NullSubstitute ist nützlich, wenn der Quellwert null ist. – cryss

0

Ich hatte das gleiche Problem Umgang mit NHibernate Entities und ich fand eine recht einfache Lösung für sie.

Sie sollten die Details-Eigenschaft im ItemViewModel-Konstruktor initialisieren. Auf diese Weise ist der Zielwert niemals null. Dies funktioniert natürlich nicht in komplexeren Fällen (wie abstrakte Klassen).

1

Hatte das gleiche Problem, aber mit EF. Crys 'Kommentar über die Verwendung von BeforeMap hat mich in die richtige Richtung gelenkt.

endete ich mit Code ähnlich der,:

Im Configure() -Methode:

Mapper.CreateMap<ItemViewModel, Item>() 
      .AfterMap((s, d) => { MapDetailsAction(s, d); }) 
      .ForMember(dest => dest.Details, opt => opt.UseDestinationValue()); 

Dann wird die Aktion:

Action<ItemViewModel, Item> MapDetailsAction = (source, destination) => 
     { 
      if (destination.Details == null) 
      { 
       destination.Details = new Details(); 
       destination.Details = 
        Mapper.Map<ItemViewModel, Item>(
        source.Details, destination.Details); 
      } 
     }; 
Verwandte Themen