Почему у AutoMapper есть IValueFormatter, когда он имеет гораздо более мощный ValueResolver? - PullRequest
15 голосов
/ 31 января 2010

Похоже, что IValueFormatter принимает значение типа object и возвращает значение типа string, тогда как ValueResolver<TSource, TDestination> принимает значение любого типа и возвращает значение любого типа. Так что это более гибко. Существует также тот факт, что с ValueResolver вам никогда не нужно приводить источник к определенному типу - вы определяете его явно в своем определении класса.

Учитывая это, зачем использовать IValueFormatter? Делает ли что-нибудь, что нельзя сделать с ValueResolver? Я неправильно понимаю, как это работает?

Ответы [ 3 ]

13 голосов
/ 02 февраля 2010

Большая разница в том, что форматеры могут применяться на уровне члена, профиля, типа и на глобальном уровне. Таким образом, вы можете сделать что-то вроде «ForSourceType.AddFormatter () в профиле, и теперь blammo! Все ваши десятичные числа теперь отображаются в виде денег. Решатели предназначены исключительно для сопоставления пользовательских элементов.

3 голосов
/ 01 февраля 2010

Хорошо, думаю, я понял это:

  • При 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)));
0 голосов
/ 01 февраля 2010

IValueFormatter - это интерфейс, который можно привязать к существующим классам или использовать вместе с какой бы то ни было библиотекой, из которой он вышел, похоже, что ValueResolver - это класс, который может иметь более широкий диапазон использования ... Иными словами, IValueFormatter, вероятно, используется для того, чтобы помочь вам использовать ваши классы с библиотекой, из которой он получен, в то время как преобразователь значений предназначен для того, чтобы помочь вам использовать их классы в вашем коде.

...