通过AutoMapper在全球应用价值解析器 [英] Globally apply value resolver with AutoMapper

查看:63
本文介绍了通过AutoMapper在全球应用价值解析器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让AutoMapper负责为我们的视图模型本地化所有DateTime属性.我们在系统中的任何地方都使用UTC,并将所有内容存储在数据库中的UTC中,但是我们希望将其自动转换为用户的时区以进行显示.

I'm trying to have AutoMapper take care of localizing all DateTime properties on our view models for us. We use UTC everywhere in our system and store everything in UTC in the database, but we'd like to automatically convert that to a user's time zone for display.

查看所有选项后,我决定使用ValueResolver.这是解析器的要旨:

After looking at all the options, I settled on using a ValueResolver. Here's the gist of the resolver:

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

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

我正在像这样设置映射:

I'm setting up the mapping like so:

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

一切正常,我对此感到满意.但是,理想情况下,我们希望视图模型上所有DateTime属性的约定默认情况下都使用此解析器.我开始思考一下视图模型的属性,选择DateTime的属性,并使用ForMember和FromMember的重载来接受属性字符串名称,但这似乎很丑陋.再加上复制AutoMapper的嵌套属性名称构建逻辑,将会很快崩溃.

This all works fine, and I'm happy with it. However, ideally we'd like a convention of all DateTime properties on a view model to use this resolver by default. I started down the path of reflecting over the view model properties, picking out DateTime ones, and using the overloads of ForMember and FromMember that take in property string names, but that seemed... ugly. Plus duplicating AutoMapper's nested property name building logic would break down pretty quick.

问题:是否有任何简单的方法可以告诉AutoMapper这样全局使用ValueResolver?要说任何时候要将源上的DateTime属性映射到目标上的DateTime属性,请使用此解析器"?

Question: Is there any easy way to tell AutoMapper to globally use a ValueResolver like this? To say "any time you're mapping a DateTime property on a source to a DateTime property on a destination, use this resolver"?

我查看了AutoMapper的测试,没有发现任何可行的方法.

I looked through AutoMapper's tests and didn't see anything that'd work.

谢谢!

推荐答案

是-但MapperRegistry的顺序略有变化.首先,创建一个从DateTime到DateTime的类型转换器:

Yes - but with a slight change in ordering of the MapperRegistry. First, create a type converter from DateTime to DateTime:

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

您的CompanyTimeConverter代码看起来很像您拥有的值解析器,只是它继承自TypeConverter.

Your CompanyTimeConverter code looks pretty much like the value resolver you had, except it inherits from TypeConverter.

接下来,您必须更改MapperRegistry的顺序(我将更改此顺序,这更有意义):

Next, you have to change the order of the MapperRegistry (I'm going to change this going forward, it makes more sense):

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

最初,可分配"(Assignable)映射器位于"TypeConverter"映射器之前,因此,如果两个类型可以彼此分配,则只需这样做即可.

Originally, the "Assignable" mapper came before the "TypeConverter" mapper, so that if two types were assignable to each other, it would just do that.

这篇关于通过AutoMapper在全球应用价值解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆