Is there any way to auto-configue Automapper to scan for all profiles in namespace/assembly? What I would like to do is to add mapping profiles to AutoMapper from given asse
In the latest versions of AutoMapper it's possible to register multiple Profile scanning one or more assemblies :
Mapper.Initialize(x => x.AddProfiles(typeof(MyMappingProfile).Assembly));
Tested with AutoMapper v. 6.0.2.0
Yeah, that would be fantastic...and exactly what I'm overhauling for V2. Scanning, registration, conventions etc.
There's not a good "What do I have" feature, but I think it would definitely be worth adding.
In .NET Core:
services.AddSingleton(this.CreateMapper());
//...
private IMapper CreateMapper()
=> new MapperConfiguration(config => config.AddMaps(Assembly.Load("Your.Project.App")))
.CreateMapper();
I found this post while searching as well, but this is how I implemented an auto mapping scheme:
public class MyCustomMap : Profile
{
protected override void Configure()
{
CreateMap<MyCustomViewModel, MyCustomObject>()
.ForMember(dest => dest.Phone,
opt => opt.MapFrom(
src => src.PhoneAreaCode + src.PhoneFirstThree + src.PhoneLastFour));
}
}
public static class AutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(x => GetConfiguration(Mapper.Configuration));
}
private static void GetConfiguration(IConfiguration configuration)
{
var profiles = typeof(MyCustomMap).Assembly.GetTypes().Where(x => typeof(Profile).IsAssignableFrom(x));
foreach (var profile in profiles)
{
configuration.AddProfile(Activator.CreateInstance(profile) as Profile);
}
}
}
So when my application starts, all I call is
AutoMapperConfiguration.Configure();
And all my maps are registered.
I have it like this, don't know if it is the best way but it works very well on pretty large project.
public class AutoMapperGlobalConfiguration : IGlobalConfiguration
{
private AutoMapper.IConfiguration _configuration;
public AutoMapperGlobalConfiguration(IConfiguration configuration)
{
_configuration = configuration;
}
public void Configure()
{
//add all defined profiles
var query = this.GetType().Assembly.GetExportedTypes()
.Where(x => x.CanBeCastTo(typeof(AutoMapper.Profile)));
_configuration.RecognizePostfixes("Id");
foreach (Type type in query)
{
_configuration.AddProfile(ObjectFactory.GetInstance(type).As<Profile>());
}
//create maps for all Id2Entity converters
MapAllEntities(_configuration);
Mapper.AssertConfigurationIsValid();
}
private static void MapAllEntities(IProfileExpression configuration)
{
//get all types from the SR.Domain assembly and create maps that
//convert int -> instance of the type using Id2EntityConverter
var openType = typeof(Id2EntityConverter<>);
var idType = typeof(int);
var persistentEntties = typeof(SR.Domain.Policy.Entities.Bid).Assembly.GetTypes()
.Where(t => typeof(EntityBase).IsAssignableFrom(t))
.Select(t => new
{
EntityType = t,
ConverterType = openType.MakeGenericType(t)
});
foreach (var e in persistentEntties)
{
var map = configuration.CreateMap(idType, e.EntityType);
map.ConvertUsing(e.ConverterType);
}
}
}
}
In version 9 of AutoMapper it can be done this way
var configuration = new MapperConfiguration(cfg =>
{
// Add all Profiles from the Assembly containing this Type
cfg.AddMaps(typeof(MyApp.SomeClass));
});
If you are using ASP.NET Core there is a helper extension to register all Profiles in Startup.ConfigureServices
// UI project
services.AddAutoMapper(Assembly.GetExecutingAssembly());
or
// Another assembly that contains a type
services.AddAutoMapper(Assembly.GetAssembly(typeof(MyApp.SomeClass)));