>  기사  >  백엔드 개발  >  AutoMapper를 사용하여 Dto와 Model 간의 무료 변환 달성(2부)

AutoMapper를 사용하여 Dto와 Model 간의 무료 변환 달성(2부)

巴扎黑
巴扎黑원래의
2016-12-20 11:31:491686검색

책은 위에서 이어집니다. 이전 기사에서는 AutoMapper를 사용하여 유형 간 1-1 매핑(Convention 및 Configuration)을 구현하는 두 가지 방법에 대해 논의하고 간단한 OO 매핑을 수행하는 방법을 배웠습니다. 이 시리즈의 마지막 기사에서는 유형 본문 유형 간의 매핑을 구현하는 방법과 두 유형에 대한 여러 매핑 규칙을 구현하는 방법을 포함하여 우리의 요구에 따라 몇 가지 중간 수준 주제에 대해 논의하고 싶습니다.
【4】타입을 타입 시스템으로 매핑
먼저 Dto와 모델을 검토하세요. BookDto가 있고 Author가 있으며 각 Author에는 고유한 ContactInfo가 있습니다. 이제 질문이 있습니다. BookDto에서 첫 번째 저자의 Author 개체를 가져오는 방법은 무엇입니까? 대답은 간단하지만 간단하지는 않습니다.
가장 간단한 방법은 앞서 언급한 CountructUsing을 사용하여 BookDto에서 Author로의 모든 필드 및 하위 유형 필드 매핑을 지정하는 것입니다.

C# 코드

var map = Mapper. CreateMap();

map.ConstructUsing(s => new Author

Name = s.FirstAuthorName,

                          ~                                                           블로그 = s. 제1저자 블로그,

                                           🎜>

                                       ~ ~    


이 접근 방식은 효과가 있을 수 있지만 매우 비경제적입니다. BookDto에서 Author로의 매핑을 처음부터 수행하고 있고 BookDto에서 ContactInfo로의 매핑이 이전에 구현되었기 때문에 실제로 다시 작성할 필요가 없습니다. ContactInfo도 포함하는 다른 Reader 유형이 있는 경우 BookDto를 Reader에 매핑할 때 BookDto -> ContactInfo 논리를 다시 작성해야 할까요? BookDto에서 Book으로의 매핑을 구현한다면 BookDto에서 Author로의 매핑 규칙을 다시 작성해야 합니까?
그래서 이런 종류의 유형 시스템 간 매핑을 위해서는 각 특정 유형에 대해 단순 매핑을 지정한 다음 복합 유형을 매핑할 때 단순 유형의 매핑을 재사용하는 것이 이상적인 접근 방식이라고 생각합니다. 더 간단한 언어로 설명하세요.
A, B, C, D의 네 가지 유형이 있습니다. 여기서 B = [C, D]입니다. A -> C, A -> D가 주어지면 A -> B를 찾으세요.
제 솔루션은 AutoMapper에서 제공하는 IValueResolver를 사용하는 것입니다. IValueResolver는 필드 수준에서 특정 매핑 논리를 구현하기 위해 AutoMapper에서 정의한 유형입니다.

C# 코드

공용 인터페이스 IValueResolver

{

ResolutionResult Resolve(ResolutionResult source)

}


실제 애플리케이션에서는 종종 일반 하위 클래스인 ValueResolver를 사용하고 이를 구현합니다. 추상 메서드:

C# 코드

protected abstract TDestination ResolveCore(TSource 소스)


여기서 TSource는 소스 유형이고 TDestination은 대상 필드입니다.
예제로 돌아가서 이제 다음과 같이 BookDto를 매핑할 수 있습니다. -> Author:

C# 코드

var map = Mapper.CreateMap( ) ;

map.ForMember(d => d.Name, opt => opt.MapFrom(s => s.FirstAuthorName))

.ForMember(d => d .Description, opt => opt.MapFrom(s => s.FirstAuthorDescription))

.ForMember(d => d.ContactInfo,

opt => opt.ResolveUsing< ;FirstAuthorContactInfoResolver>()));


FirstAuthorContactInfoResolver에서 ValueResolver를 구현하고 BookDto를 재사용합니다. -> ContactInfo 로직:

C# 코드

FirstAuthorContactInfoResolver : ValueResolver

{

protected override ContactInfo ResolveCore(BookDto source)

{

return Mapper.Map< ;BookDto, ContactInfo> ;(출처);

}  

}  


모든 작업이 완료되었습니다.
마찬가지로 이제 BookDto -> Book을 구현할 수 있죠? BookDto -> Author 및 BookDto ->
정말 가능할까요? 아직 문제가 있는 것 같습니다. 예, BookDto에서 두 명의 다른 작성자로 매핑해야 하며 해당 필드 매핑 규칙이 다르다는 것을 알게 될 것입니다. 무엇을 해야 할까요? 마지막 주제로 빠르게 넘어가겠습니다.
【5】두 가지 유형에 대한 여러 매핑 규칙 세트 구현
문제는 유형 A와 B에 대해 2개의 서로 다른 A -> B를 정의하고 동시에 사용할 수 있도록 허용해야 한다는 것입니다. 실제로 현재 AutoMapper는 이를 수행하기 위한 미리 만들어진 방법을 제공하지 않습니다.
물론 "국가를 구하기 위한 곡선" 방법을 사용할 수 있습니다. FirstAuthor 및 SecondAuthor와 같이 첫 번째 저자와 두 번째 저자에 대해 Author의 두 하위 클래스를 정의한 다음 BookDto -> > 하지만 이 방법 역시 그다지 경제적이지는 않습니다. 세 번째 저자나 네 번째 저자가 있는 경우에는 어떻게 되나요? 각 저자에 대한 Author 하위 클래스를 정의하시겠습니까?
반면에 AutoMapper가 그러한 기능을 제공한다면 어떤 모습일까요? CreateMap 메서드와 Map 메서드는 다음과 같이 정의되어야 합니다.

C# 코드

CreateMap(string tag)

Map(TSource , string tag)


매핑의 태그를 식별하는 데 사용되는 추가 매개변수 태그가 있습니다.
이를 사용하면 다음을 수행할 수 있습니다.

C# 코드

var firstAuthorMap = Mapper.CreateMap("first")

// BookDto 정의 -> 첫 번째 작성자 규칙

var secondAuthorMap = Mapper.CreateMap("second")

// BookDto 정의 -> 작성자 규칙

var firstAuthor = Mapper.Map(출처, "첫 번째")

var secondAuthor = Mapper.Map(출처, "두 번째" );


안타깝지만 이것이 전부입니다. AutoMapper가 이 문을 닫았지만 우리에게는 MappingEngine이라는 또 다른 문이 남았습니다.
MappingEngine은 AutoMapper의 매핑 실행 엔진입니다. 실제로 Mapper에는 기본 MappingEngine이 있습니다. Mapper.CreateMap을 호출하면 이 기본 MappingEngine을 호출한 후 Configuration에 규칙을 작성합니다. 객체의 경우 기본 MappingEngine이 해당 구성의 규칙을 실행하는 데 사용됩니다.
간단히 말하면 MappingEngine은 AutoMapper의 "가상 머신"입니다. 동시에 여러 "가상 머신"을 시작하고 서로 다른 "가상 머신"에 동일한 유형 쌍에 대해 서로 다른 매핑 규칙을 적용하면 다음을 수행할 수 있습니다. 평화롭게 실행되도록 하세요. 사용할 때 해당 "가상 머신"에 어떤 규칙을 사용할지 물어보세요.
그냥 하세요. 먼저 MappingEngineProvider 클래스를 정의하고 이를 사용하여 다양한 MappingEngine을 얻습니다.

C# 코드

public class MappingEngineProvider

{

private readonly MappingEngine _engine;

public MappingEngine Get()

{ >

}

다양한 유형의 매핑 규칙을 인터페이스 IMapping으로 추상화합니다. :

C# 코드


공용 인터페이스 IMapping

{

void AddTo(Configuration config)

}

그런 다음 필요한 규칙을 MappingEngineProvider 생성자의 해당 MappingEngine에 넣습니다.

C# 코드


private static Dictionary> ; _rules=new Dictionary>();

public MappingEngineProvider(엔진 엔진)

{

var config = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers())

_rules[engine].ForEach(r=> r.AddTo(config))

_mappingEngine MappingEngine(config);

}

열거형 엔진을 사용하여 가능한 MappingEngine을 식별했습니다.

C# 코드


공개 열거형 엔진

{

기본 = 0,

첫째,

둘째

}

우리는 3개의 엔진을 사용하는데, Basic은 모든 기본 매핑 규칙을 배치하는 데 사용되고, First는 모든 Dto -> FirstXXX 규칙을 배치하는 데 사용되며, Second는 모든 Dto -> SecondXXX 규칙을 배치하는 데 사용됩니다.

또한 모든 매핑 규칙을 배치하는 사전 _rule을 정의하고 규칙을 여러 엔진으로 분류합니다.

남은 유일한 일은 매핑으로 Dictionary_rule을 채우는 것입니다. 예를 들어 첫 번째 엔진에 BookDtoToFirstAuthorMapping을 배치하고 두 번째 엔진에 BookDtoToSecondAuthorMapping을 배치합니다.


C# 코드

private static readonly Dictionary> 🎜>
새 사전>

                                 Engine.First, 새 목록

       ~

new BookDtoToFirstAuthorMapping(),

}

                                                                 >                                        {                                                          다양한 MappingEngineProvider 개체를 미리 인스턴스화할 수 있습니다.

C# 코드

public static SimpleMappingEngineProvider First = new MappingEngineProvider(Engine.First);

public static SimpleMappingEngineProvider Second = new MappingEngineProvider(Engine.Second)

이제 이 두 엔진을 사용할 수 있습니다. BookDto를 매핑할 때 -> Book을 사용하여 2명의 Author를 필드로 조립합니다. Authors:

C# 코드

public class BookDtoToBookMapping: DefaultMapping 🎜>

{

protected override void MapMembers(IM ApplyExpression< ;BookDto, Book> map)

{

map.ForMember(d => d.Authors ,

opt => op t.ResolveUsing() ; 🎜>

protected override ListResolveCore(BookDto 소스)


🎜>
var secondAuthor = SimpleMappingEngineProvider.Second.Get().Map(소스) ? secondAuthor.IsNull() ? new List {새 작성자(), secondauthor}

: Secondauthor.isnull()

? w 목록 & lt; {firstautHor}

: new List {firstAuthor, secondAuthor} 🎜>

}

마지막으로, 이 섹션의 시작 부분에서 언급한 좋은 점을 기억하시나요? AutoMapper는 구현에 도움이 되지 않았으므로 직접 구현해 보겠습니다.

C# 코드

public class MyMapper


{

private static 읽기 전용 사전 엔진 = 새 사전                                                          🎜>

                                                                                                      Engine.First, MappingEngineProvider.First.Get()},

                                                        두 번째.Get()},

                                                                

public static TTarget Map(TSource 소스, 엔진 엔진 = Engine.Basic)

{

return Engines[엔진].Mapvar firstAuthor = MyMapper.Map(dto, Engine.First);

var secondAuthor = MyMapper.Map(dto, Engine.Second);

은 다음과 같을 수도 있습니다:

C# 코드

var book = MyMapper.Map(dto)

추첨: 집에서 Github에 파일을 업로드하는 것이 매우 느린 것을 발견하여 먼저 코드를 패키지하여 업로드하기로 결정했습니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.