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.