2009-11-03 7 views
12

Wystąpiły pewne poważne problemy z automapper. Myślę, że znalazłem rozwiązanie, ale nie wiem, jak go wdrożyć.Używanie wersji CreateMap i Map z usługą WCF za pomocą instancji?

zasadniczo używam niestandardowego mapowania z ResolveUsing i ConstructedBy, aby przekazać parametry konstruktorowi, rozumiem, że większość ludzi ustawiła to raz w global.asax i zapomniała o tym.

Ale problemem jest to, że moja metoda (na WCF) przechodzi w różnych params do konstruktora z ResolveUsing ......

Przed używałem Mapper.CreateMap i Mapper.Map które są statyczne metody i wydaje się, że gdy różne petycje wchodzą do usługi wcf za pośrednictwem metod (multi-user), są ze sobą sprzeczne.

Po przeczytaniu czegoś pojawia się możliwość użycia wersji CreateMap i Map w wersji instancji, dzięki czemu każda indywidualna petycja otrzymuje własną mapę i może przekazywać własne parametry.

Ale nie mogę znaleźć sposobu na zrobienie tego. Czy ktoś może wyjaśnić proszę? Naprawdę utknąłem ...

Przede wszystkim otrzymywałbym zduplikowane błędy klucza, a także wstawiałem ślad dziennika na konstruktorze i wygląda na to, że 1 petycja nadpisuje drugą - stąd statyczne wersje Mappera.

No mam nadzieję, że jestem poprawne, ale nie mogę znaleźć nic innego ...

EDYCJI - przykładem tego, co mam

Zasadniczo wszystko mapowanie działa tak jak powinien, jak Używam MapFrom w większości przypadków.

Następnie tworzę instancję mojego Resolvera, którą przekazuję pod adres URL. Sprawdziłem adres URL, zanim go podaję i jest on poprawny. Ale po zwróceniu zwraca nieprawidłowy adres URL.

Powodem, dla którego muszę podać URL jest to, że zawiera on zmienne, więc muszę wymienić zmienne ... Zasadniczo istnieją 2 adresy URL w zależności od biura i mam dzienniki wszędzie i mogę zobaczyć, co jestem przechodzi, ale kiedy go minie - to nie jest ten, który minąłem, jeśli to ma sens, to jest dziwne !!

Jest to usługa WCF, a klient nazwał tę metodę dwukrotnie w dwóch różnych biurach, stąd 2 różne adresy URL. Ale zawsze zwracają ten sam adres URL. To tak, jakby jedna sesja nadpisała drugą ...

Mam nadzieję, że to ma sens.

SalesPointResolver newSalesPointResolver = new SalesPointResolver(returnReservationUrl, reservationSite.ReservationUrl, startDate, endDate, officeCode); 


     Mapper.CreateMap<Models.Custom.House, DTO.House>() 
      .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)) 
      .ForMember(dest => dest.TaxIncluded, 
         opt => opt.MapFrom(src => src.Segments.FirstOrDefault().TaxIncluded)) 
      .ForMember(dest => dest.TaxPercentage, 
         opt => opt.MapFrom(src => src.Segments.FirstOrDefault().TaxPercentage)) 

      .ForMember(dest => dest.SalesPoints, 
         opt => 
         opt.ResolveUsing(newSalesPointResolver)) 
      ; 

dowiedział się, gdzie zawodzi - ale wiadomo dlaczego

zobacz moje komentarze inline z kodu. W konstruktorze przychodzi urlTemplate, zapisuję go w prywatnym var, a następnie w przesłoniętym ResolveCore jest coś innego :-)

Umieściłem tam kilka log-logów, więc mogę zobaczyć, co się dzieje.

[Log] 
public class SalesPointResolver : ValueResolver<Models.Custom.House, IList<DTO.SalesPoint>> 
{ 
    private readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    private string urlTemplate; 

    public SalesPointResolver (bool returnReservationUrl, string urlTemplate, DateTime startDate, DateTime endDate, string officeCode) 
    { 
     this.urlTemplate = urlTemplate; 

     log.Error("passed in " + urlTemplate); // THIS IS PERFECT 
     log.Error("I am now " + this.urlTemplate); // THIS IS PERFECT 
    } 

    protected override IList<DTO.SalesPoint> ResolveCore(House source) 
    { 
     this.house = source; 

     log.Error("in resolveCore :" + this.urlTemplate); // THIS IS RETURNING THE WRONG VALUE 

rozwiązanie tymczasowe

Zrobiłem tymczasowe rozwiązanie, ale jest naprawdę źle. Jestem pewien, że automapper może zrobić to, co próbuję, ale oczywiście robię coś nie tak.

Zasadniczo wracam za pośrednictwem LINQ do zbioru rekordów (TO JEST MOJE ŹRÓDŁO), więc wprowadziłem nowe pole do każdego rekordu, w którym znajduje się poprawny szablon adresu URL. A następnie, zamiast przekazywać (poprzez konstruktor) szablon adresu URL, mam go dostępny jako właściwość na KAŻDY rekord w kolekcji (THE SOURCE) ... i działa idealnie.

Oczywiście, to naprawdę jest łatka, a nie idealna, ale działa.

Gdzie się mylę?

+0

W przykładzie jest to, że nie znamy źródła aż do czasu wykonywania ale wiesz, do którego celu mapujesz podczas kompilacji? –

+0

Nie znam źródła ... ale przekazuję zmienne do ResolveUsing przy użyciu konstruktora, dlatego mapa musi być tworzona za każdym razem i nie musi być współużytkowana przez żadną inną sesję itp. –

+0

Jeśli jest to usługa WCF, to działa ona w swoim własna domena aplikacji, więc mapy nie będą udostępniane żadnym innym procesom. Wygląda na to, że argumenty dla ResolveUsing są różne, ale ResolveUsing zwykle przyjmuje typ źródłowy. Jaki jest sens przekazywania argumentów do konstruktora niestandardowego narzędzia Resolver wartości, który jest poza typem źródła? –

Odpowiedz

2

Więc wydaje się, że moje pytanie jest opuszczony, ale po dość podczas zabawy w końcu znalazłem dobrą poprawkę ..

zasadzie byłem wewnątrz Resolve i miałem inną mapę, która jedna z właściwości o nazwie inny ResolveUsing ...

Wygląda na to, że istnieje problem z tym. Inną dziwną rzeczą jest to, że nie powiodło się za każdym razem, gdy pula aplikacji została uruchomiona lub poddana recyklingowi. Stąd nie powiodło się za pierwszym razem, a następnie było ok, dopóki nie doszło do recyklingu (korzystam z aplikacji wcf).

Więc ja zastąpiła drugą mapowania zz foreach i zrobił mój odwzorowanie takiego w moim oryginalnym Resolve ...

Włożyłem odpowiedź tutaj w przypadku może pomóc nikogo innego w przyszłości ..

używałem odwzorowującego metody statyczne zrobić moje mapowania, nie były w global.asax jak muszę przechodzić różne rzeczy w zależności od pewnych czynników ..

zawsze zastanawiałem się, czy byłoby możliwe, aby to zrobić z wersjami mapppera instancji, chociaż istniała ..... ale nigdy się nie dowiedział ..

Ale mimo to wszystko działa w 100% teraz ...

+0

Czy możesz odpowiedzieć http://stackoverflow.com/questions/9498962/contract-first-soa-designing-business-domain-wcf? – Lijo

1

Czy przyjrzeli się Państwo użyciu wywołania Map, które przyjmuje obiekt docelowy?

var bar = nowy pasek ("Niestandardowe każde połączenie");

Mapper.Map (foo, bar);

+0

Dzięki jimmy, Nie jestem pewien f całkiem rozumiem. Jeśli zmienię mapę, to nie będę miał dostępu do mojego standardowego obiektu src, który jest mi potrzebny, ponieważ normalnie odwzorowuję go tylko na kilku właściwościach, które wymagają ode mnie wywołania specjalnego parametru ResolveUsing i podania parametru, ponieważ jest całkiem sporo logiki tutaj ... Tak więc w rozwiązaniu za pomocą nadal używam mojego standardowego obiektu src, ale stosuję dodatkową logikę przed powrotem (w tym przypadku stringg) - czy nie rozumiem cię? –

+0

jeśli mógłbyś rozwinąć, bardzo bym to docenił. –

+0

Myślę, że źle zrozumiałem - czy masz mały urywek, który pokazuje, w jaki sposób używasz wywołań CreateMap i Map? –

34

Tak, istnieje sposób, aby użyć wersji instancji AutoMapper.

Zamiast ...

Mapper.CreateMap<Dto.Ticket, Entities.Ticket>() 

można użyć:

var configurationStore = 
    new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers); 
var mapper = new MappingEngine(configurationStore); 
configurationStore.CreateMap<Dto.Ticket, Entities.Ticket>() 
+20

Nie wiem o starszych wersjach AutoMappera, ale w aktualnej wersji klasa 'Configuration' nosi nazwę' ConfigurationStore'. –

+2

A metoda 'AllMappers()' jest obecnie właściwością o nazwie 'Mappers'. – bugged87

13

W odpowiedzi na Luke Woodwards „s comment na nowszych składnię:

ConfigurationStore store 
    = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers); 
store.AssertConfigurationIsValid(); 
MappingEngine engine = new MappingEngine(store); 

//add mappings via Profiles or CreateMap 
store.AddProfile<MyAutoMapperProfile>(); 
store.CreateMap<Dto.Ticket, Entities.Ticket>(); 
Powiązane problemy