Using Profiles in Automapper to Map the Same Types with Different Logic

Using Profiles in Automapper to map the same types with different logic

Profiles are for segregating common configuration applied across several type maps, like formatting. However, type maps are still global. 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.

Different mapping rules for same entity types in AutoMapper

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

Create two Automapper maps between the same two object types

Kevin Kalitowski raised a good point about wal's answer: If we need two configurations to deal with a mapping that needs to be different, then don't we have to duplicate all the other mappings that are common?

I think I've found a way around this using profiles: Have one profile for each of the unique mappings, and a third profile for the common mappings. Then create two configurations, one for each unique profile but also add the common profile to each configuration as well.

Example, in AutoMapper 4.2:

The classes to be mapped: User and Vehicle:

public class User
{
public string Name { get; set; }
public int Age { get; set; }
}

public class Vehicle
{
public int FleetNumber { get; set; }
public string Registration { get; set; }
}

The profiles:

public class Profile1 : Profile
{
protected override void Configure()
{
base.CreateMap<User, User>();
}
}

public class Profile2 : Profile
{
protected override void Configure()
{
base.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
}
}

public class CommonProfile : Profile
{
protected override void Configure()
{
base.CreateMap<Vehicle, Vehicle>();
}
}

Then create the configurations and map the objects:

[TestMethod]
public void TestMethod()
{
var user = new User() { Name = "John", Age = 42 };
var vehicle = new Vehicle {FleetNumber = 36, Registration = "XYZ123"};

var configuration1 = new MapperConfiguration(cfg =>
{
cfg.AddProfile<CommonProfile>();
cfg.AddProfile<Profile1>();
});

var mapper1 = configuration1.CreateMapper();
var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age
var mappedVehicle1 = mapper1.Map<Vehicle, Vehicle>(vehicle);//Maps both FleetNumber
//and Registration.

var configuration2 = new MapperConfiguration(cfg =>
{
cfg.AddProfile<CommonProfile>();
cfg.AddProfile<Profile2>();
});

var mapper2 = configuration2.CreateMapper();
var mappedUser2 = mapper2.Map<User, User>(user);//maps only Name
var mappedVehicle2 = mapper2.Map<Vehicle, Vehicle>(vehicle);//Same as mappedVehicle1.
}

I tried this out and it works.

AutoMapper with different instances

Thank you for reply friends. I found the solution. Before and after using AutoMapper, I reset the AutoMapper

    AutoMapper.Mapper.Reset();

and it worked.Refer this link
http://blog.cymen.org/2011/06/17/automapper-and-mapper-reset/



Related Topics



Leave a reply



Submit