Глобальное применение преобразователя значений с помощью AutoMapper - PullRequest
17 голосов
/ 14 апреля 2011

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

После просмотра всех опций я остановился на использовании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 и не видел ничего, что могло бы работать.

Спасибо!

1 Ответ

14 голосов
/ 15 апреля 2011

Да, но с небольшим изменением порядка 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», так что еслидва типа были назначены друг другу, он просто сделал бы это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...