Register automapper profiles with autofac
AutoMapper is simple library that takes care of Object-to-Object mappings which is otherwise boring & redundant to code every-time. An example scenario would be creating a Data Transfer Objects(DTOs) from a Data Model (Entity).
The map configuration is usually done once per App domain so you would probably add it in the Application startup like global.asax
. This would mean that you need to do a reference of all namespaces that contains mapping in your app startup file like below
Mapper.Initialize(cfg => cfg.CreateMap<Com.Davidsekar.Order, Com.Davidsekar.OrderDto>());
//or
var config = new MapperConfiguration(cfg => cfg.CreateMap<Com.Davidsekar.Order, Com.Davidsekar.OrderDto>());
So to overcome this type of concrete references,
AutoMapper offers a way to group all map creation as an AutoMapper Profile within its respective namespaces, which allows you to keep the map registration within its library.
namespace Com.Davidsekar.Models.Mapping
{
using AutoMapper;
using Com.Davidsekar.Models.Data;
using Com.Davidsekar.Models.Dto;
public class ContactFormMappingProfile : Profile
{
#region Constructors
public ContactFormMappingProfile()
{
CreateMap<ContactForm, ContactFormDto>().ReverseMap();
}
#endregion Constructors
}
}
You can keep the mappings in the AutoMapper profile class within library and then, these individual profiles can be easily scanned and initialized using Autofac using following code
/// <summary>
/// Registers the AutoMapper profile from the external assemblies.
/// </summary>
/// <param name="builder">The builder.</param>
private static void RegisterMaps(ContainerBuilder builder)
{
var assemblyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
var assembliesTypes = assemblyNames
.Where(a => a.Name.Equals("Com.Davidsekar.Models", StringComparison.OrdinalIgnoreCase))
.SelectMany(an => Assembly.Load(an).GetTypes())
.Where(p => typeof(Profile).IsAssignableFrom(p) && p.IsPublic && !p.IsAbstract)
.Distinct();
var autoMapperProfiles = assembliesTypes
.Select(p => (Profile)Activator.CreateInstance(p)).ToList();
builder.Register(ctx => new MapperConfiguration(cfg =>
{
foreach (var profile in autoMapperProfiles)
{
cfg.AddProfile(profile);
}
}));
builder.Register(ctx => ctx.Resolve<MapperConfiguration>().CreateMapper()).As<IMapper>().InstancePerLifetimeScope();
}
In above code, we are scanning through all referenced assemblies for an assembly with a particular name and then, try to register all the types with type AutoMapper Profile
. You can very well convert that single assembly name to a List<string> of assembly names.
The above sample code give you a gist on how you can dynamically register all mapper configurations. Share your views.