2011-04-14 5 views
17

Я пытаюсь, чтобы AutoMapper позаботился о локализации всех свойств DateTime на наших моделях просмотра для нас. Мы используем UTC всюду в нашей системе и сохраняем все в UTC в базе данных, но мы хотели бы автоматически преобразовать это в часовой пояс пользователя для отображения.Глобально применить преобразователь значений с помощью AutoMapper

Изучив все варианты, я решил использовать ValueResolver. Вот суть разрешителе:

public class LocalizedDateTimeFormatter : ValueResolver<DateTime, DateTime> 
{ 
    protected override DateTime ResolveCore(DateTime source) 
    { 
     // get company 

     return company.TimeZone.ConvertFromUtc(source); 
    } 
} 

Я настраиваю отображение следующим образом:

Mapper.CreateMap<Entity, Model>() 
    .ForMember(dest => dest.Foo, opt => opt.ResolveUsing<LocalizedDateTimeFormatter>() 
              .FromMember(src => src.Foo)); 

Это все работает отлично, и я счастлива с ним. Однако в идеале мы бы хотели, чтобы по умолчанию все свойства DateTime в модели представления использовали для использования этого резольвера. Я начал путь к отражению свойств модели представления, выделению DateTime и использованию перегрузок ForMember и FromMember, которые принимают имена строк свойств, но это казалось ... уродливым. Плюс дублирование логики построения вложенных свойств AutoMapper будет довольно быстро разрушаться.

Вопрос: Есть ли простой способ сказать AutoMapper глобально использовать ValueResolver, как это? Чтобы сказать: «В любое время, когда вы сопоставляете свойство DateTime с источником в свойство DateTime в конечном месте, используйте этот резольвер»?

Я просмотрел тесты AutoMapper и не видел ничего, что сработало бы.

Спасибо!

+0

Это отличный вопрос, и я буду это обычным требованием. Мне не повезло, что я попытался выполнить это в ответ на ответ Джимми. Кто-нибудь знает о рабочем примере? –

ответ

14

Да - но с небольшими изменениями в упорядочении MapperRegistry. Во-первых, создать преобразователь типа из DateTime в DateTime:

Mapper.CreateMap<DateTime, DateTime>().ConvertUsing<CompanyTimeConverter>(); 

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

Далее, вы должны изменить порядок MapperRegistry (я собираюсь изменить это движение вперед, это имеет смысл):

MapperRegistry.AllMappers =() => new IObjectMapper[] { 
    new DataReaderMapper(), 
    new TypeMapMapper(TypeMapObjectMapperRegistry.AllMappers()), 
    new StringMapper(), 
    new FlagsEnumMapper(), 
    new EnumMapper(), 
    new ArrayMapper(), 
    new EnumerableToDictionaryMapper(), 
    new DictionaryMapper(), 
    new ListSourceMapper(), 
    new CollectionMapper(), 
    new EnumerableMapper(), 
    new TypeConverterMapper(), 
    new AssignableMapper(), 
    new NullableMapper() 
}; 

Первоначально «Назначаемые» картографа пришел до того, как " TypeConverter ", так что, если бы два типа были назначены друг другу, он просто сделал бы это.

+1

Удивительный, спасибо Джимми! Мне действительно не нужно было менять порядок MapperRegistry, чтобы заставить его работать. Я запускаю AutoMapper 1.1.0.188. –

+0

есть ли способ сделать это на уровне профиля? Я не думаю, что изменения в MapperRegistry могут быть изолированы. – chester89

+1

Что делать, если вы используете AutoMapper для сопоставления как из объекта, так и для просмотра модели, а затем обратно из модели представления в объект (например, при редактировании объекта)? Как вы можете сказать AutoMapper только для отображения в одном направлении или для использования ConvertFromUtc в одном направлении и ConvertToUtc в другом? – Farinha

Смежные вопросы