2012-06-21 20 views
25

Dziś uaktualniłem w pełni działającą aplikację przy użyciu AutoMapper v1.1, aby teraz używać AutoMapper v2.1 i napotykam na problemy, których nigdy nie spotkałem przy użyciu poprzedniej wersji.AutoMapper używa niewłaściwego konstruktora

Oto przykład mojego mapowania kodu z powrotem Dto do Domain obiektu

public class TypeOne 
{ 
    public TypeOne() 
    { 
    } 

    public TypeOne(TypeTwo two) 
    { 
     //throw ex if two is null 
    } 

    public TypeOne(TypeTwo two, TypeThree three) 
    { 
     //throw ex if two or three are null 
    } 

    public TypeTwo Two {get; private set;} 

    public TypeThree Three {get; private set;} 
} 

public class TypeOneDto 
{ 
    public TypeOneDto() 
    { 
    } 

    public TypeTwoDto Two {get; set;} 

    public TypeThreeDto Three {get; set;} 
} 

...

Mapper.CreateMap<TypeThreeDto, TypeThree>(); 
Mapper.CreateMap<TypeTwoDto, TypeTwo>(); 
Mapper.CreateMap<TypeOneDto, TypeOne>(); 

var typeOne = Mapper.Map<TypeOne>(typeOneDto); 

Jednakże pierwszy problem jaki napotkaliśmy był z v2.1 że AutoMapper próbował użyć konstruktora z 2 argumentami, gdy jeden z argumentów był zerowy i powinien używać 1 konstruktora arg.

Potem próbował użyć

Mapper.CreateMap<TypeOneDto, TypeOne>().ConstructUsing(x => new TypeOne()); 

Ale ciągle otrzymuję „Niejednoznaczne Invocation” błąd, że nie mogę rozwiązać.

Następnie próbowałem

Mapper.CreateMap<TypeOneDto, TypeOne>().ConvertUsing(x => new TypeOne()); 

a nie z powodzeniem utworzyć obiekt TypeOne używając konstruktora bez parametrów, ale wtedy nie udało się ustawić właściwości setter prywatnych.

Szukałem pomocy na stronie AutoMappera i ściągnąłem kod źródłowy, aby dobrze się przyjrzeć, ale nie dałem rady z małą dokumentacją i nie było zbyt wielu testów jednostkowych dla ConstructUsing.

Czy brakuje mi czegoś oczywistego, co powinienem zmienić w wersji 2.1? Jestem zaskoczony, że tak bardzo się zmieniło od wersji 1.1.

+0

możliwe duplikat [Automapper - jak mapować do parametrów konstruktora zamiast ustawiaczy mienia] (http://stackoverflow.com/questions/2239143/automapper-how-to-map-to-constructor-parameters- zamiast ustawiania właściwości) –

+0

Ciągle otrzymuję ten sam błąd, o którym wspomniałem powyżej, kiedy używam "ConstructUsing". "Niejednoznaczne wywołanie" podczas tworzenia nowego obiektu z konstruktorem bez parametrów. –

Odpowiedz

48

Wystarczy dodać explicit cast do

Func<ResolutionContext, TypeOne> 

Oto kod:

Mapper.CreateMap<TypeOneDto, TypeOne>().ConstructUsing(
      (Func<ResolutionContext, TypeOne>) (r => new TypeOne())); 

Aktualna wersja AutoMapper działa jak opisano poniżej:

  1. Sortowanie typu konstruktorzy przeznaczenia według liczby parametrów

    destTypeInfo.GetConstructors().OrderByDescending(ci => ci.GetParameters().Length); 
    
  2. Wykonuje pierwszy konstruktor, którego parametry pasują do właściwości źródła (bez sprawdzania wartości pustej). W twoim przypadku jest to konstruktor z dwoma parametrami.

+0

To tylko uratowało mi trochę żalu. Działa idealnie na najnowszej wersji AutoMappera (3.2.1.0) :) Dzięki! – Stu1986C

+3

Chociaż jest to dość stary post, cieszę się, że go znalazłem: Sekwencja tego, co AutoMapper uważa za dopasowanie dla konstruktora, wydaje się, że zmieniła się ponownie w wersji 4.0.4. Aby uniknąć problemów, po stronie bardziej konserwatywnej zawsze należy określić, którego konstruktora AutoMapper powinien użyć, jeśli masz więcej niż jeden konstruktor. Ponadto, jako drugie zalecenie, mamy zautomatyzowany test, który ustawia wszystkie mapy, a następnie wywołuje "Mapper.AssertConfigurationIsValid()". W ten sposób możesz szybko rozwiązać problemy. Szczęśliwe kodowanie! – Manfred

Powiązane problemy