Хорошо, думаю, я понял это:
При IValueFormatter
вход для метода FormatValue()
является фактическим значением. (Ладно, технически, это объект ResolutionContext
, который позволяет вам получить значение, используя свойство SourceValue
, но вы поняли идею).
При ValueResolver
вход для метода ResolveCore()
представляет собой весь источник (а не только значение источника).
Итак, если вы хотите выполнить какое-то преобразование между исходным значением и значением назначения, IValueFormatter
будет работать только в том случае, если тип назначения равен string
, а ValueResolver
будет работать только в том случае, если ResolveCore()
метод «знает», какое свойство использовать (что не будет иметь место, если ваш распознаватель имеет общее назначение, т. Е. Не применяется к определенному свойству).
Обход
К счастью, всегда есть MapFrom
, который обеспечивает гибкость, которой не хватает как для распознавателей, так и для форматеров.
Интерфейс преобразователя
Я закончил тем, что написал интерфейс для простой и гибкой обработки того, что я считаю очень распространенным сценарием: двусторонние преобразования ...
public interface ITwoWayConverter<TInput, TOutput>
{
TOutput ConvertForward(TInput value);
TInput ConvertBackward(TOutput value);
}
Пример конвертера:
public class PhoneNumberToString : ITwoWayConverter<long, string>
{
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<User, UserViewModel>()
.ForMember(dest => dest.PhoneNumber, opt => opt
.MapFrom(orig => new PhoneNumberToString().ConvertForward(orig.PhoneNumber)));