web-dev-qa-db-fra.com

Automapper: mapper les propriétés manuellement

Je viens juste de commencer à utiliser automapper pour mapper les entités DTO <-> et cela semble fonctionner parfaitement.

Dans certains cas particuliers, je souhaite mapper uniquement certaines propriétés et effectuer des vérifications supplémentaires. Sans automapper, le code ressemble à ceci (en utilisant PropertyExtensions de FastFlect):

object target;
object source;
string[] changedPropertyNames = { };

foreach (var changedPropertyName in changedPropertyNames)
{
    var newValue = source.GetPropertyValue(changedPropertyName);
    target.SetPropertyValue(changedPropertyName, newValue);
}

Bien entendu, ce code ne fonctionnera pas si des conversions de types sont requises. Automapper utilise TypeConverters intégré et j'ai également créé des implémentations spécifiques de TypeConverter.

Maintenant, je me demande s'il est possible de mapper des propriétés individuelles et d'utiliser l'implémentation de conversion de type d'automapper, quelque chose comme ceci

Mapper.Map(source, target, changedPropertyName);

Mettre à jour

Je pense que plus d'informations sont nécessaires:

J'ai déjà créé des cartes, par exemple.

Mapper.CreateMap<CalendarEvent, CalendarEventForm>()

et j'ai également créé une carte avec un convertisseur de type personnalisé pour la propriété nullable dateTime dans CalendarEvent, par exemple.

Mapper.CreateMap<DateTimeOffset?, DateTime?>().ConvertUsing<NullableDateTimeOffsetConverter>();

J'utilise ces cartes dans un contrôleur Web api OData. Lors de la publication de nouveaux EntityDTO, j’utilise

Mapper.Map(entityDto, entity);

et enregistrez l’entité dans un magasin de données. 

Mais si vous utilisez PATCH, un Delta<TDto> entityDto est transmis à mes méthodes de contrôleur. Par conséquent, je dois appeler entityDto.GetChangedPropertyNames() et mettre à jour mon entité persistante existante avec les valeurs modifiées.

Fondamentalement, cela fonctionne avec ma solution simple, mais si l’une des propriétés modifiées est par ex. un DateTimeOffset? J'aimerais utiliser mon NullableDateTimeOffsetConverter.

8
krombi

Si vous souhaitez uniquement mapper une propriété sélectionnée, procédez comme indiqué ci-dessous. 

// Create a map
var map = CreateMap<Source,Target>();
// ingnore all existing binding of property
map.ForAllMembers(opt => opt.Ignore());
// than map property as following
map.ForMember(dest => dest.prop1, opt => opt.MapFrom( src => src.prop1));
map.ForMember(dest => dest.prop2, opt => opt.MapFrom( src => src.prop2));
17
Pranay Rana

Vous pouvez faire des projections en utilisant MapFrom method - http://automapper.readthedocs.io/en/latest/Projection.html

Mapper.Map(source, target)
   .ForMember(m => m.Property, opt => opt.MapFrom(src => src.ChangedProperty));

Par exemple (en référence à la documentation AutoMapper):

// Model
var calendarEvent = new CalendarEvent
    {
        Date = new DateTime(2008, 12, 15, 20, 30, 0),
        Title = "Company Holiday Party"
    };

// Configure AutoMapper
Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
    .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
    .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.Date.Hour))
    .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.Date.Minute));
7
Pawel Maga

Si j'ai bien lu votre question, oui, tant que votre propriété de destination (cible) correspond à votre conversion.

Donc, si je passe d'une string à une bool pour une Status de "A" ou "I" (actif/inactif), je peux faire quelque chose comme:

.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status == "A"))

Et puis, dans l'autre sens, reconvertissez-le:

.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status ? "A" : "I"))

Un exemple de date:

.ForMember(dest => dest.SomeDate, opt => opt.MapFrom(src => src.SomeDate.ToString("M/d/yyyy")));
1
Mark C.