Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different mapping rules for same entity types in AutoMapper

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?

like image 325
Afshin Gh Avatar asked Jun 08 '13 02:06

Afshin Gh


People also ask

Does AutoMapper map private fields?

AutoMapper will map property with private setter with no problem. If you want to force encapsulation, you need to use IgnoreAllPropertiesWithAnInaccessibleSetter.

Is AutoMapper a singleton?

Your configuration (e.g. Automapper Profiles) are singletons. That is, they are only ever loaded once when your project runs. This makes sense since your configurations will not change while the application is running.


1 Answers

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
like image 199
Afshin Gh Avatar answered Sep 29 '22 01:09

Afshin Gh