AutoMapper는 객체 간 매핑을 처리하는 간단한 라이브러리로, 반복적이고 지루한 코드 작성을 줄여줍니다. 대표적인 사용 예로 데이터 모델(Entity)로부터 데이터 전송 객체(DTO)를 생성하는 작업이 있습니다.
매핑 설정은 일반적으로 애플리케이션 도메인당 한 번만 수행되므로 global.asax와 같은 애플리케이션 시작 파일에 추가하게 됩니다. 이 경우 아래와 같이 매핑 관련 모든 네임스페이스를 참조해야 합니다.
Mapper.Initialize(cfg => cfg.CreateMap<Com.Davidsekar.Order, Com.Davidsekar.OrderDto>());
//또는
var config = new MapperConfiguration(cfg => cfg.CreateMap<Com.Davidsekar.Order, Com.Davidsekar.OrderDto>());
이러한 구체적인 참조 문제를 해결하기 위해, AutoMapper는 관련 네임스페이스 내에서 매핑 생성을 그룹화할 수 있는 AutoMapper Profile 기능을 제공합니다. 이를 통해 라이브러리 내부에 매핑 등록을 유지할 수 있습니다.
namespace Com.Davidsekar.Models.Mapping
{
using AutoMapper;
using Com.Davidsekar.Models.Data;
using Com.Davidsekar.Models.Dto;
public class ContactProfile : Profile
{
public ContactProfile()
{
CreateMap<ContactForm, ContactFormDto>().ReverseMap();
}
}
}
라이브러리 내의 AutoMapper 프로필 클래스에 매핑을 유지한 다음, 이러한 개별 프로필들을 Autofac을 사용하여 쉽게 스캔하고 초기화할 수 있습니다.
/// <summary>
/// 외부 어셈블리에서 AutoMapper 프로필을 등록합니다.
/// </summary>
/// <param name="container">컨테이너 빌더.</param>
private static void ConfigureMappings(ContainerBuilder container)
{
var targetAssemblyName = "Com.Davidsekar.Models";
var loadedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
var profileTypes = loadedAssemblies
.Where(assembly => assembly.Name.Equals(targetAssemblyName, StringComparison.OrdinalIgnoreCase))
.SelectMany(assemblyInfo => Assembly.Load(assemblyInfo).GetTypes())
.Where(type => typeof(Profile).IsAssignableFrom(type) && type.IsPublic && !type.IsAbstract)
.ToList();
var mappingProfiles = profileTypes
.Select(type => (Profile)Activator.CreateInstance(type))
.ToArray();
container.Register(context => new MapperConfiguration(config =>
{
foreach (var profile in mappingProfiles)
{
config.AddProfile(profile);
}
})).SingleInstance();
container.Register(context => context.Resolve<MapperConfiguration>().CreateMapper())
.As<IMapper>()
.InstancePerLifetimeScope();
}
위 코드에서는 참조된 모든 어셈블리 중 특정 이름의 어셈블리를 검색하고, AutoMapper Profile 타입의 모든 클래스를 등록합니다. 단일 어셈블리 이름을 문자열 리스트로 확장하여 여러 어셈블리를 대상으로 할 수도 있습니다.
이 샘플 코드는 모든 매퍼 설정을 동적으로 등록하는 방법에 대한 핵심 개념을 보여줍니다.