2009-11-03 1 views
12

Имеет некоторые реальные проблемы с automapper. Я думаю, что нашел решение, но не знаю, как его реализовать.Использование версии экземпляра CreateMap и Map с помощью службы WCF?

В основном я использую настраиваемое сопоставление с ResolveUsing и ConstructedBy для передачи в params конструктору, я понимаю, что большинство людей задают это в global.asax один раз и забывают об этом.

Но проблема в том, что мой метод (на ФОС) проходит в разных Params к конструктору ResolveUsing ......

Прежде чем я использовал Mapper.CreateMap и Mapper.Map, которые являются статические методы, и кажется, что, когда различные запросы поступают в службу wcf с помощью методов (multi -user), они конфликтуют друг с другом.

После прочтения чего-то я могу использовать экземплярную версию CreateMap и Map, чтобы каждое отдельное ходатайство получало свою собственную карту и могло передавать свои собственные параметры.

Но я не могу найти, как это сделать. Может ли кто-нибудь объяснить, пожалуйста? Я действительно застрял ...

Раньше я получал повторяющиеся ключевые ошибки, а также добавлял трассировку журнала в конструктор, и оказалось, что 1 петиция переписывает другую - следовательно, статические версии Mapper.

Ну, я надеюсь, что я правильно, но я не могу найти что-нибудь еще ...

EDITED - пример того, что я

В основном все отображения работает, как должно, так как В большинстве случаев я использую MapFrom.

Затем я создаю экземпляр моего резольвера, который я передаю по URL-адресу. Я проверил URL-адрес, прежде чем передать его и правильно. Но как только он вернется, он вернет неправильный URL.

Причина, по которой мне нужно пройти по URL-адресу, заключается в том, что в нем есть переменные, поэтому мне нужно заменить переменные ... В основном есть два URL-адреса в зависимости от офиса, и у меня есть журналы везде, и я могу видеть, что я проходя, но как только я передаю его - это не тот, в который я прошел, если это имеет смысл, это странно!

Его служба WCF и клиент вызвали метод, дважды проходящий в 2 разных офисах, следовательно, два разных URL-адреса. Но они всегда возвращают один и тот же URL. Это похоже на то, что одна сессия перезаписывает другую ...

Надеюсь, это имеет смысл.

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)) 
      ; 

разузнала, где не удается - НО ПОЧЕМУ UNKNOWN

Смотрите мои комментарии рядный с кодом. В конструкторе появляется urlTemplate, я сохраняю его в приватном var, а затем в переопределенном ResolveCore это что-то еще :-)

Я разместил там журналы log4net, поэтому я вижу, что происходит.

[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 

ВРЕМЕННОЕ РЕШЕНИЕ

Я сделал временное решение, но это действительно плохо. Я уверен, что automapper может делать то, что я пытаюсь, но я, очевидно, делаю что-то неправильно.

В основном я возвращаю через LINQ коллекцию записей (ЭТО МОЙ ИСТОЧНИК), поэтому я ввел новое поле в каждую запись, в которой есть правильный шаблон URL. И затем вместо того, чтобы передавать (через конструктор) шаблон url, я имею его как свойство в КАЖДОЙ записи в коллекции (ИСТОЧНИК) ... и он отлично работает.

Конечно, это действительно патч и не идеальный, но он заставляет меня бежать.

Куда я иду не так?

+0

В вашем примере это, что вы не знаете источника до выполнения но вы знаете, какую цель вы планируете во время компиляции? –

+0

Нет, я знаю источник ... но я передаю переменные в ResolveUsing с использованием конструктора, следовательно, карта должна создаваться каждый раз и не должна использоваться другим сеансом и т. Д. –

+0

Если это служба WCF, она работает в ее собственный домен приложения, поэтому карты не будут использоваться ни с каким другим процессом. Похоже, что аргументы ResolveUsing различаются, но ResolveUsing обычно использует тип источника. Какова аргументация для того, чтобы вы передавали аргументы в конструктор вашего настраиваемого Value Resolver, который находится вне вашего типа источника? –

ответ

2

Ну кажется, что мой вопрос отказался, но после того, как давненько играли вокруг, я, наконец, нашел хороший фикс ..

в основном я был внутри Resolve и я имел другую карту, которая одна из свойств под название другого ResolveUsing ...

Кажется, что проблема связана с этим. Еще одна странность в том, что она не срабатывала каждый раз, когда пул приложений запускался или перерабатывался. Следовательно, это не удалось в первый раз, а затем было нормально, пока не произошла перезагрузка (я использую приложение wcf).

Так я заменил второй картографированию с с Еогеасп и сделал свое отображение, как, что внутри моей первоначальной Resolve ...

Я положил ответ здесь в случае, если это может помочь кому-либо еще в будущем ..

Я использовал Mapper статические методы, чтобы сделать мои отображения, они были не в global.asax, как мне нужно, чтобы передать разные вещи в зависимости от определенных факторов ..

Я всегда задавался вопросом, будет ли это возможно сделать с экземплярами версий mappper, хотя он и существовал ..... но так и не узнал ..

Но в любом случае все работает 100% теперь ...

+0

Не могли бы вы ответить на http://stackoverflow.com/questions/9498962/contract-first-soa-designing-business-domain-wcf? – Lijo

1

Вы просматривали использование вызова карты, который принимает объект назначения?

var bar = new Bar («Пользовательский каждый вызов»);

Mapper.Map (foo, bar);

+0

Спасибо, jimmy, Не уверен, что я Я вполне понимаю. Если я изменю карту, то у меня не будет доступа к стандартному объекту src, который мне нужен, поскольку я обычно сопоставляю его только по нескольким свойствам, которые требуют, чтобы я вызывал специальный ResolveUsing и передавал параметр, поскольку есть довольно немного логики здесь ... Таким образом, при разрешении использования я все еще использую свой стандартный объект src, но применяя дополнительную логику перед возвратом (в данном случае stringg) - я не понимаю вас? –

+0

Если бы вы могли разработать, я бы очень его оценил. –

+0

Я думаю, что я неправильно понял - есть ли у вас небольшой фрагмент, который показывает, как вы используете вызовы CreateMap и Map? –

1

Если вы хотите использовать инстанс версию Mapper в Automapper, то я думаю, что вы можете использовать класс MappingEngine. Я считаю, что статический класс Mapper создает экземпляр и настраивает объект MappingEngine, чтобы выполнить всю работу по сортировке nitty.

Вот пример применения IoC к Automapper (что требует создания экземпляра MappingEngine)

http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/05/11/automapper-and-ioc.aspx

34

Да, есть способ использовать версию экземпляра AutoMapper.

Вместо ...

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

вы можете использовать:

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

Я не знаю более старых версий AutoMapper, но в текущей версии класс 'Configuration' имеет имя' ConfigurationStore'. –

+2

И метод 'AllMappers()' теперь является свойством 'Mappers'. – bugged87

13

В ответ на Luke Woodwards «s comment на более новый синтаксис:

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>();