11
votes

I have two entities: Order & OrderDTO And I'm using AutoMapper to map them together.

Based on some conditions I want these entities to be mapped differently.

In fact I want two or more different mapping rules (CreateMap) for these entities.

And When calling Map function I want to tell the engine which mapping rule to use.

Thanks to this question: Using the instance version of CreateMap and Map with a WCF service? one approach is using a different instance of mapper so each one can has it's own mapping rules:

var configuration = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.AllMappers());
var mapper = new MappingEngine(configuration);
configuration.CreateMap<Dto.Ticket, Entities.Ticket>()

Do you have any better solution?

As mentioned by Jimmy Bogard (Creator of AutoMapper) here: Using Profiles in Automapper to map the same types with different logic :

You're better off creating separate Configuration objects, and creating a separate MappingEngine for each. The Mapper class is merely a static facade over each of those, with some lifecycle management.

What lifecycle management is needed to be done?

2
I am trying to figure out the same thing. I've seen that answer but I don't get the way it works. Hope someone could help. Cheers.LeftyX
@LeftyX: checkout my answer.Afshin Gh

2 Answers

3
votes

I've ended up creating a new instance of mapper and caching them in a shared(static) concurrent dictionary.

here s my code (vb.net):

mapper factory:

Public Function CreateMapper() As IMapper Implements IMapperFactory.CreateMapper
            Dim nestedConfig = New ConfigurationStore(New TypeMapFactory, MapperRegistry.Mappers)
            Dim nestedMapper = New MappingEngine(nestedConfig)
            Return New AutomapperMapper(nestedConfig, nestedMapper)
 End Function

different profiles for different scenarios:

Private Shared _mapperInstances As New Concurrent.ConcurrentDictionary(Of String, IMapper)

Public Shared ReadOnly Property Profile(profileName As String) As IMapper
            Get
                Return _mapperInstances.GetOrAdd(profileName, Function() _mapperFactory.CreateMapper)
            End Get
End Property

and the mapper class:

Friend Class AutomapperMapper
        Implements IMapper

        Private _configuration As ConfigurationStore
        Private _mapper As MappingEngine

        Public Sub New()
            _configuration = AutoMapper.Mapper.Configuration
            _mapper = AutoMapper.Mapper.Engine
        End Sub

        Public Sub New(configuration As ConfigurationStore, mapper As MappingEngine)
            _configuration = configuration
            _mapper = mapper
        End Sub

        Public Sub CreateMap(Of TSource, TDestination)() Implements IMapper.CreateMap
            _configuration.CreateMap(Of TSource, TDestination)()
        End Sub

        Public Function Map(Of TSource, TDestination)(source As TSource, destination As TDestination) As TDestination Implements IMapper.Map
            Return _mapper.Map(Of TSource, TDestination)(source, destination)
        End Function

        Public Function Map(Of TSource, TDestination)(source As TSource) As TDestination Implements IMapper.Map
            Return _mapper.Map(Of TSource, TDestination)(source)
        End Function


    End Class
2
votes

I came across the same problem and I found that AutoMapper is upgraded to 4.2.0 one month ago, which begins to support instances mappers created by different configurations, and the static mapper functions are marked obsoleted. So we don't need to implement by ourselves from now on!