2017-04-04 4 views
2

매핑되지 않은 속성이 누락 된 매핑 된 속성을 대상 개체의 사전에 매핑하려면 AutoMapper를 어떻게 만들 수 있습니까? (직렬화시처럼 ExtensionData)매핑되지 않은 속성을 사전/ExtensionData에 매핑

예 :

이제
class Source 
{ 
    public int A {get;set;} 
    public int B {get;set;} 
    public int C {get;set;} 
} 

class Destination 
{ 
    public int A {get;set;} 
    public Dictionary<string, object> D {get;set;} 
} 

Source s = new Source { A = 1, B = 2, C = 3 }; 
Destination d = ... // Mapping code 

나는 다음과 같은 결과 원하는 :

d.A ==> 1 
d.D ==> {{ "B", 2 }, { "C", 3 }} 

* EDIT * 결국

내가 찾는 오전 솔루션 반사없이. 의미 : 설정/구성/초기화 중에 반영이 허용되지만 매핑 자체 중에는 반영으로 인한 지연을 원하지 않습니다.

* EDIT *

난 그냥 시리얼과 같은 일반적인 솔루션을 찾고 있어요.

+0

을, 그러나 당신은 소스를 비교하는 반사를 사용하는 사용자 지정 해결을 만들 수 있으며, 대상 속성을 찾고 거기에서 이동하십시오. –

+0

나는 이미 사용자 지정자와 씨름하고있다 ...하지만 그것은 고통이다. 시리얼 라이저가이 기능을 가지고 있기 때문에 내가 처음으로이 인터페이스를 사용하고 있다고 상상할 수 없습니다.이 기능은 데이터를 한 객체의 데이터를 다른 객체로 매핑하기 때문에 가능합니다. –

답변

4

문제에 대해 가능한 많은 해결책이 있습니다. 나는 당신의 속성에 대해 사용자 정의 값 해결 프로그램을 작성했습니다 그것은 완벽하게 작동합니다 :

public class CustomResolver : IValueResolver<Source, Destination, Dictionary<string, object>> 
{ 
    public Dictionary<string, object> Resolve(Source source, Destination destination, Dictionary<string, object> destMember, ResolutionContext context) 
    { 
     destMember = new Dictionary<string, object>(); 

     var flags = BindingFlags.Public | BindingFlags.Instance; 
     var sourceProperties = typeof(Source).GetProperties(flags); 

     foreach (var property in sourceProperties) 
     { 
      if (typeof(Destination).GetProperty(property.Name, flags) == null) 
      { 
       destMember.Add(property.Name, property.GetValue(source)); 
      } 
     } 

     return destMember; 
    } 
} 

방법을 사용할 수 있나요?

static void Main(string[] args) 
{ 
    Mapper.Initialize(cfg => { 
     cfg.CreateMap<Source, Destination>() 
      .ForMember(dest => dest.D, opt => opt.ResolveUsing<CustomResolver>()); 
    }); 

    var source = new Source { A = 1, B = 2, C = 3 }; 

    var result = Mapper.Map<Source, Destination>(source); 
} 

public class Source 
{ 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; set; } 
} 

public class Destination 
{ 
    public int A { get; set; } 
    public Dictionary<string, object> D { get; set; } 
} 
+0

좋은 해결책. 속도가 느리기 때문에 리플렉션을 사용하여 데이터 읽기/쓰기를 방지하기 위해 AutoMapper를 선택합니다. AutoMapper는 해당 프로세스를 최적화합니다. 나는 결과적으로 어떤 중요한 지연없이 완전한 최적화 된 매핑 프로세스를 갖출 수 있기를 바라고있었습니다. 안 ... 너 +1. –

+0

나는 나의 질문을 편집했다. 그래서 당신은 대답을 정말로 더 이상 기준에 부합하지 않는다. 그러나 다시 : 나를위한 아주 좋은 출발. –

+0

AutoMapper가 Reflection을 사용 중입니다. https://msdn.microsoft.com/en-us/library/system.reflection.emit(v=vs.110).aspx 리플렉션없이 매핑되지 않은 속성을 검색 할 가능성이 있는지 확실하지 않습니다. –

2

저는 Pawel의 솔루션이 더 일반적이기 때문에 좋아합니다. 당신은 간단하지만 덜 일반적인 뭔가를 원하는 경우에이 같은 매퍼 초기화 할 수있다 : 나는이 작업을 수행 할 수있는 붙박이 기능이있다 생각하지 않는다

Mapper.Initialize(cfg => { 
          cfg.CreateMap<Source, Destination>() 
           .ForMember(dest => dest.D, 
             opt => opt.MapFrom(r => new Dictionary<string,object>(){{ "B", r.B},{ "C", r.C}})); 
    }); 
+0

고맙습니다. 예 일반적인 솔루션을 찾고 있습니다. 여전히 +1. –