为什么AutoMapper有一个看似更强大的ValueResolver时会有一个IValueFormatter?

它看起来像IValueFormatter获取type类型的值并返回string类型的值,而ValueResolver获取任何类型的值并返回任何类型的值。 所以,它更灵活。 还有一个问题是,使用ValueResolver ,您永远不需要将源转换为特定类型 – 您可以在类定义中明确定义它。

鉴于此,为什么要使用IValueFormatter ? 它是否可以执行ValueResolver无法完成的任何操作? 我误解了它是如何工作的吗?

最大的区别是格式化程序可以应用于成员,配置文件,类型和全局级别。 因此,您可以在配置文件中执行类似“ForSourceType.AddFormatter()”的操作,现在就是blammo!所有小数现在都显示为money。解析器严格用于自定义成员映射。

好的,我想我已经弄明白了:

  • 使用IValueFormatterFormatValue()方法的输入是实际值。 (好的,从技术上讲,它是一个ResolutionContext对象,可以让你使用SourceValue属性获取值,但你明白了)。

  • 使用ValueResolverResolveCore()方法的输入是整个源(不仅仅是源值)。

因此,如果要在源值和目标值之间进行某种转换,则IValueFormatter仅在目标类型为string时才起作用,而ValueResolver仅在ResolveCore()方法“知道”哪个属性时才起作用使用(如果您的解析器是通用的,则不会是这种情况,即不适用于特定的财产)。

解决方法

幸运的是,总有MapFrom ,它提供了解析器和格式化程序所缺乏的灵活性。

转换器接口

我最后编写了一个界面来简单灵活地处理我认为是一种非常常见的情况:双向转换……

 public interface ITwoWayConverter { TOutput ConvertForward(TInput value); TInput ConvertBackward(TOutput value); } 

示例转换器:

 public class PhoneNumberToString : ITwoWayConverter { public string ConvertForward(long value) { return string.Format("{0:(###) ###-####}", Convert.ToInt64(value)); } public long ConvertBackward(string value) { return Convert.ToInt64(Regex.Replace(value, @"\D", string.Empty)); } } 

用法示例:

 Mapper.CreateMap() .ForMember(dest => dest.PhoneNumber, opt => opt .MapFrom(orig => new PhoneNumberToString().ConvertForward(orig.PhoneNumber))); 

IValueFormatter是一个接口,可以添加到现有的类中,也可以与它出来的库一起使用,看起来ValueResolver是一个可能有更广泛使用范围的类……换句话说,IValueFormatter可能用于帮助您使用它来自的库,而值解析器旨在帮助您在代码中使用它们的类。