使用AutoMapper在全球范围内应用值解析器

时间:2011-04-14 16:22:21

标签: automapper

我正在尝试让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 个答案:

答案 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”映射器之前,因此如果两个类型可以相互分配,它就会这样做。