WPF Prism에서 AutoMapper 사용하기

WPF Prism에서 AutoMapper 사용하기

AutoMapper

AutoMapper는 서로 다른 두 클래스를 보다 쉽게 매핑하기 위해 사용하는 라이브러리이다. 내 경우(그리고 많은 오픈소스 프로젝트의 경우) 모델과 DTO 사이의 매핑을 손쉽게 처리하기 위해 주로 사용된다.

Prism

Prism 프레임워크, 또는 라이브러리1이전 포스트에서 자세히 다룬 바 있다. 다시 간략하게 정리하자면 MVVM 기반 프로젝트 개발을 더 쉽게 할 수 있도록 도와주는 프레임워크이다.

Prism에서 AutoMapper DI하기

ASP.NET 프로젝트에서 AutoMapper 사용은 정말 쉽다. 애초에 AutoMapper에서 확장 메서드를 제공하기 때문에 서비스를 구성할 때 해당 메서드를 호출하고, AutoMapper.Profile을 상속받은 클래스를 만들어 아무 곳에다가 배치해놓은 뒤 실행하면 된다.

그러나 Prism용 확장 메서드는 자체적으로 제공되지 않으므로 직접 만들어 써야 한다.

IAutoMapperProvider interface

일단 DI를 위해 사용할 인터페이스부터 구성한다.

public interface IAutoMapperProvider
{
    IMapper GetMapper();
}

AutoMapperProvider class

이제 위 인터페이스를 상속한 AutoMapperProvider 클래스를 작성한다.

public class AutoMapperProvider : IAutoMapperProvider
{
    private readonly MapperConfiguration _configuration;

    public AutoMapperProvider(IContainerProvider containerProvider)
    {
        _configuration = new MapperConfiguration(config =>
        {
            config.ConstructServicesUsing(containerProvider.Resolve);

            config.AddMaps(AppDomain.CurrentDomain.GetAssemblies());
        });
    }

    public IMapper GetMapper()
    {
        return _configuration.CreateMapper();
    }
}

AutoMapperProvider 클래스 역시 DI 기반으로 동작할 것이기 때문에 생성자에서 IContainerProvider를 주입받고 이를 사용해 MapperConfiguration 필드를 초기화한다.

MapperConfiguration은 내부적으로 IContainerProvider.Resolve 메서드를 사용해 서비스를 빌드하게 된다. 또한, 직접 AutoMapper.Profile 인스턴스를 하나 하나 등록하지 않고 ASP.NET에서 사용하듯 자동으로 검색해 등록하도록 AddMaps를 설정한다.

GetMapper에서는 이렇게 구성된 MapperConfiguration 객체를 사용하여 새 매퍼 인스턴스를 반환하도록 한다.

의존성 주입

이제 주입해야 하는 코드에서(App.xaml.cs 등) 설정을 완료하면 된다.

private IMapper GetMapper(IContainerProvider containerProvider)
{
    var provider = containerProvider.Resolve<IAutoMapperProvider>();

    return provider.GetMapper();
}

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterSingleton<IAutoMapperProvider, AutoMapperProvider>();
    containerRegistry.Register(typeof(IMapper), GetMapper);
}

공급자는 싱글톤으로 구성하고, 매퍼 인스턴스는 transient로 구성하여 올바르게 작동하도록 한다.

사용

이제 원하는 곳에서 주입하여 사용할 수 있다.

public class AViewModel
{
    private readonly IMapper _mapper;

    public AViewModel(IMapper mapper)
    {
        _mapper = mapper;
    }

    // ...

    public void AMapperUsesIMapper()
    {
        _mapper.Map<TypeA>(instance);
    }
}

  1. 프리즘 홈페이지에서조차 둘을 혼용해 사용한다. 직접 써보니 라이브러리보단 프레임워크 개념에 가까웠다. ↩︎

댓글

이 블로그의 인기 게시물

C# 남아도는 메모리에도 불구하고 OutOfMemoryException이 발생한다면?

USB를 뒤는 괜찮은데 앞에 꽂으면 인식이 힘들다?

MySQL 데이터 타입과 Java 데이터 타입 비교/매칭