Brea
Brea

Reputation: 41

Automapper - Set collection items field in the current context

I'm trying to map an Enumerable collection of items from class Source to an Enumerable collection of Destination class obj. Class Destination derives from Class Source, and it differs only for a boolean property.

public class Source
{
 public string ID {get;set;}
 public string Color {get;set:}
}

public class Destination : Source
{
 public bool IsDefault {get;set;}
}

I have a container class as follows:

public class Container
{
  public string DeafultID {get;set;}
  public Enumerable<Source> SourceCollection {get;set}
}

I want to map the SourceCollection property of Container class to a Enumerable collection, where IsDefault is true only for the single element with ID == DefaultID.

Something like:

var container = Contailer.Build();

var newCollection = automapper.Map<IEnumerable<Source>, IEnumerable<Destination>>(container.SourceCollection)
.something(destinationItem.IsDefault = (sourceItem.ID == DefaultID));

Upvotes: 1

Views: 312

Answers (2)

Fab
Fab

Reputation: 51

For a more readable solution, I suggest you to proceed element by element projecting through a select the entire collection, handling the property in that context.

var myCollection = container.SourceCollection.Select(item => MapSingleItem(item, cointainer.DefaultId);

private Destination MapSingleItem(Source item, string defaultId)
{
    var mappedItem = _mapper.Map<Source, Destination>(item);
    mappedItem.IsDefault = (mappedItem.ID == defaultId);

    return mappedItem;
}

Upvotes: 1

Jeff Mercado
Jeff Mercado

Reputation: 134571

You would have to pass in the contextual info needed for the mapping when you call the map function. Just make sure to use the value in your map through the provided ResolutionContext. You'll need to use the overload that exposes it in your mappings.

var autoMapper = new AutoMapper.Mapper(new AutoMapper.MapperConfiguration(c =>
{
    c.CreateMap<Source, Destination>()
        .ForMember(
            x => x.IsDefault,
            m => m.MapFrom((x,_,_,c) => x.ID == ((Container)c.Items[nameof(Container)]).DefaultID)
        );
}));
var destinationCollection = autoMapper.Map<IEnumerable<Destination>>(
    container.SourceCollection,
    c => c.Items[nameof(Container)] = container
);

You may want to add this as an extension method on your container class to make mapping a little nicer to call against.

internal static class ContainerExtensions
{
    internal static T Map<T>(this Container container, IMapper mapper, object source) =>
        mapper.Map<T>(source, c => c.Items[nameof(Container)] = container);
}

// usage:
var destinationCollection = container.Map<IEnumerable<Destination>>(autoMapper, container.SourceCollection);

Upvotes: 2

Related Questions