The current DTO mapping strategy using private nested classes within each DTO can be cumbersome and disorganized, especially as the number of DTOs grows. This makes it so you have to make the default map everytime a DTO is created.
I'd suggest a reflection-driven MappingProfile that uses this IMapFrom<> interface. This will automatically register all mappings in the assembly, creating default maps just by using the interface and giving the developer the ability to override if there's a need for a custom map.
Here’s a snippet of the suggested additions:
public class MappingProfile : Profile
{
public MappingProfile()
=> this.ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
private void ApplyMappingsFromAssembly(Assembly assembly)
{
var types = assembly
.GetExportedTypes()
.Where(t => t
.GetInterfaces()
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>)))
.ToList();
foreach (var type in types)
{
var instance = Activator.CreateInstance(type);
const string mappingMethodName = "Mapping";
var methodInfo = type.GetMethod(mappingMethodName)
?? type.GetInterface("IMapFrom`1")?.GetMethod(mappingMethodName);
methodInfo?.Invoke(instance, new object[] { this });
}
}
}
using AutoMapper;
public interface IMapFrom<T>
{
void Mapping(Profile mapper) => mapper.CreateMap(typeof(T), this.GetType());
}
The current DTO mapping strategy using private nested classes within each DTO can be cumbersome and disorganized, especially as the number of DTOs grows. This makes it so you have to make the default map everytime a DTO is created.
I'd suggest a reflection-driven MappingProfile that uses this IMapFrom<> interface. This will automatically register all mappings in the assembly, creating default maps just by using the interface and giving the developer the ability to override if there's a need for a custom map.
Here’s a snippet of the suggested additions: