.net - asp - ¿Cómo escanear y configurar automáticamente los perfiles en AutoMapper?
automapper profile c# (6)
¿Hay alguna forma de autoconfigurar Automapper para buscar todos los perfiles en espacio de nombres / ensamblaje? Lo que me gustaría hacer es agregar perfiles de mapeo a AutoMapper desde un ensamblado dado filtrado por una interfaz dada, algo así como Explorar convenciones en StructureMap:
public static void Configure()
{
ObjectFactory.Initialize(x =>
{
// Scan Assembly
x.Scan(
scanner =>
{
scanner.TheCallingAssembly();
scanner.Convention<MyCustomConvention>();
scanner.WithDefaultConventions();
});
// Add Registries
x.AddRegistry(new SomeRegistry());
});
Debug.WriteLine(ObjectFactory.WhatDoIHave());
}
public class MyCustomConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (!type.CanBeCastTo(typeof(IMyType)))
{
return;
}
string name = type.Name.Replace("SomeRubishName", String.Empty);
registry.AddType(typeof(IMyType), type, name);
}
He intentado usar SelfConfigure pero no puedo encontrar ninguna documentación sobre cómo usarlo para filtrar perfiles:
public static void Configure()
{
Mapper.Initialize(x =>
{
// My Custom profile
x.AddProfile<MyMappingProfile>();
// Scan Assembly
x.SelfConfigure(Assembly.GetCallingAssembly());
});
}
Otra pregunta es ¿cómo puedo reportar todos los mapas / perfiles ya iniciados (algo como ObjectFactory.WhatDoIHave () en StructureMap)?
En las últimas versiones de AutoMapper es posible registrar múltiples perfiles explorando uno o más conjuntos:
Mapper.Initialize(x => x.AddProfiles(typeof(MyMappingProfile).Assembly));
Probado con AutoMapper v. 6.0.2.0
Lo tengo así, no sé si es la mejor manera pero funciona muy bien en un proyecto bastante grande.
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);
}
}
}
}
Sí, eso sería fantástico ... y exactamente lo que estoy revisando para V2. Escaneo, registro, convenciones etc.
No hay una buena característica "¿Qué tengo?", Pero creo que definitivamente valdría la pena agregarla.
Similar a la respuesta de @Martino, pero con un objeto MapperConfiguration. Esto agregará todos los perfiles del ensamblaje que contiene el tipo MyProfile.
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfiles(typeof(MyProfile));
});
var mapper = config.CreateMapper();
También encontré esta publicación durante la búsqueda, pero así es como implementé un esquema de asignación automática:
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);
}
}
}
Así que cuando mi aplicación comienza, todo lo que llamo es
AutoMapperConfiguration.Configure();
Y todos mis mapas están registrados.
public class AutoMapperAdapter : IMapper
{
private readonly MapperConfigurationExpression _configurationExpression =
new MapperConfigurationExpression();
public void AssertConfigurationIsValid() { Mapper.AssertConfigurationIsValid(); }
public void CreateMap<TSource, TDestination>()
{
_configurationExpression.CreateMap<TSource, TDestination>();
}
public void Initialize() { Mapper.Initialize(_configurationExpression); }
public TDestination Map<TDestination>(object source)
{
return Mapper.Map<TDestination>(source);
}
}