jasontaylordev / CleanArchitecture

Clean Architecture Solution Template for ASP.NET Core
MIT License
16.75k stars 3.6k forks source link

Implement Universal Reflection-Driven MappingProfile for Cleaner DTOs #1167

Closed ImSk1 closed 5 months ago

ImSk1 commented 5 months ago

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.

image

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());
  }
ramax495 commented 5 months ago

This approach was used in this solution before and it had been recently simplified to current manual mapping. https://github.com/jasontaylordev/CleanArchitecture/pull/871