Introduction
I am using AutoMapper version 5.1.1.0 with IMapper interface (as opposed to static class Mapper).
IMapper
interface is injected into constructors of my classes by Unity framework, but you can use any other DI framework or inject IMapper
interface manually.
Motivation
I really like automapper functionality and I find it really useful especially when binding objects between layers. And I had a real struggle to make this work. So this should hopefully be a simple tutorial for those who would like to move from static Mapper
class to IMapper
interface. Or for those who never used AutoMapper
before and would like to learn how to wire it all up. Because most of the tutorials I found were incomplete or out of date (using static Mapper
class).
One Layer
If you have only one layer where you need to map between your models, I would recommend not to use AutoMapper Profiles and just go with a simple solution.
public static class MappingProfile
{
public static MapperConfiguration InitializeAutoMapper()
{
MapperConfiguration config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Question, QuestionModel>();
cfg.CreateMap<QuestionModel, Question>();
});
return config;
}
}
This way, you create your MapperConfiguration
object with all your mappings.
You can then create IMapper
object from this configuration and inject it into your DI framework (Unity in my case).
public static class UnityWebActivator
{
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
var mapper = MappingProfile.InitializeAutoMapper().CreateMapper();
container.RegisterInstance<IMapper>(mapper);
FilterProviders.Providers.Remove
(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
On line 7, MapperConfiguration
is created and from that configuration by calling .CreateMapper()
we get IMapper
object.
On line 8, IMapper
interface is binded to this mapper object (from line 7).
So from now, every time when DI sees IMapper
object in constructor, it will provide this mapper object (line 7 again).
Now, example of object that requires IMapper
:
public class BaseService
{
protected IMapper _mapper;
public BaseService(IMapper mapper)
{
_mapper = mapper;
}
public void AutoMapperDemo(){
var questions = GetQuestions(token);
return _mapper.Map<IEnumerable<Question>,
IEnumerable<QuestionModel>>(questions);
}
public IEnumerable<Question> GetQuestions(token){
}
}
This could be usage of automapper. You can use IMapper
interface public
method Map<>
to map your classes. IMapper
object is injected either by DI framework or manually when you create the BaseService
object.
More Than One Layer
In the real world MVC application, you usually have more than one layer. You probably have something like WEB/BUSINESS/DB layer and WEB should not know about DB, because it talks only to BUSINESS layer.
That means with one configuration class you would have to reference DB project in your Web layer, otherwise you couldn’t map your objects.
And here comes for help automapper Profiles.
MappingProfile class again, now with profiles:
public static class MappingProfile
{
public static MapperConfiguration InitializeAutoMapper()
{
MapperConfiguration config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new WebMappingProfile());
cfg.AddProfile(new BLProfile());
});
return config;
}
}
public class WebMappingProfile : Profile
{
public WebMappingProfile()
{
CreateMap<Question, QuestionModel>();
CreateMap<QuestionModel, Question>();
}
}
public class BLProfile: Profile
{
public BLProfile()
{
CreateMap<BLModels.SubModels.Address, DataAccess.Models.EF.Address>();
}
}
This way Web layer doesn’t need to reference DB layer.
All other steps are the same as for one layer.
Summary
I think that automapper can be a very useful tool if used properly, but it is sometimes really hard to find tutorials that are up to date. I highly recommend you to read autommaper wiki if you struggle.
I encourage you to write in comments how to wire this with for example Ninject or Castle Windsor.