Подтвердить что ты не робот

Справочная реализация для IFormattable

Есть ли хорошая ссылочная реализация для IFormattable? Я планирую иметь хотя бы один пользовательский IFormatProvider для моего объекта, и я хочу убедиться, что проводка верна для разных возможных наборов параметров, переданных в IFormattable.ToString(string, IFormatProvider).

Что я до сих пор:

public class MyDataClass : IFormattable
{
    /// <seealso cref="IFormattable.ToString(string, IFormatProvider)"/>
    public string ToString(string format, IFormatProvider formatProvider)
    {
        ICustomFormatter formatter = (ICustomFormatter)formatProvider.GetFormat(typeof(ICustomFormatter));
        return formatter.Format(format, this, formatProvider);
    }
}

Но, похоже, существуют другие потенциальные ситуации, которые должны быть охвачены, то есть:

  • Если formatProvider равно null, я должен вернуться к this.ToString()?
  • Если formatProvider.GetFormat(typeof(ICustomFormatter)) возвращает null, есть ли конкретное исключение, которое я должен бросить?

Приветствуются любые записи в блогах/примеры кода/ссылки MSDN.

4b9b3361

Ответ 1

Похоже, вы неправильно понимаете дизайн инфраструктуры форматирования .NET Framework. ICustomFormatter никогда не следует ссылаться на реализацию IFormattable.ToString, поскольку это противоречит намеченной цели этого интерфейса.

IFormattable

Объект должен реализовывать только IFormattable, если он знает, как отформатировать себя (в идеале он должен делегировать это другому классу, но здесь было бы намеренное соединение). Объект может знать, как отформатировать себя несколькими разными способами, поэтому строка формата позволяет выбирать между ними. Даже при этом все еще может быть недостающая информация, такие вещи, которые различаются по культуре. Поэтому есть второй параметр, который косвенно предоставляет такую ​​информацию.

Тип, переданный в IFormatProvider.GetFormat, предназначен для типа или интерфейса, специфичных для класса IFormatProvider.

Например, встроенные числовые типы хотят получить экземпляр System.Globalization.NumberFormatInfo, а связанные классы DateTime хотят получить System.Globalization.DateTimeFormatInfo.

Реализация IFormattable

Итак, представьте себе, что мы создаем новый класс самоформатов. Если он знает только один способ форматирования, он должен просто переопределить object.ToString() и не более того. Если класс знает более одного способа форматирования, он должен реализовать IFormattable.

Параметр format

Per документация IFormattable.ToString поддерживается форматная строка "G" (которая представляет общий формат) должна. Рекомендуется, чтобы строка нулевого или пустого формата была эквивалентна строке формата "G". Точное значение для нас в противном случае.

Параметр formatProvider

Если нам нужна какая-либо специфическая культура или которая в противном случае будет изменяться, нам нужно использовать параметр IFormatProvider. Какой-то тип, который мы запрашиваем, используя IFormatProvider.GetFormat. Если значение IFormatProvider равно null, или если IFormatProvider.GetFormat возвращает null для типа, который мы хотим, мы должны вернуться к некоторому источнику по умолчанию для этой различной информации.

Источник по умолчанию не обязательно должен быть статическим. Вполне возможно, что источником по умолчанию может быть пользовательский параметр в приложении, а formatProvider используется для предварительного просмотра изменений параметров и/или когда для сериализации необходим фиксированный формат.

Также возможно, что форматирование может включать форматирование некоторого под-объекта. В этом случае вы, вероятно, захотите передать IFormatProvider вниз. MSDN имеет отличный пример реализации IFormattable, который показывает этот самый случай.

Другие ToString перегрузки

При реализации IFormattable важно, чтобы object.ToString() было переопределено способом, эквивалентным следующему

public override string ToString()
{
    return this.ToString(null, System.Globalization.CultureInfo.CurrentCulture);
}

Это гарантирует, что somestring + yourobject эквивалентен string.Format("{0}{1}",somestring, yourobject), который ваши пользователи будут ожидать.

Для удобства пользователей вы должны, возможно, предоставить string ToString(string format). Кроме того, если ваш формат по умолчанию имеет различные компоненты, которые могут извлечь выгоду из IFormatProvider, вы также можете предоставить public string ToString(IFormatProvider provider).

ICustomFormatter

Итак, что нам делать, если мы хотим отформатировать класс, который не знает, как отформатировать себя, или мы хотим использовать какой-то формат, не поддерживаемый самим классом. То есть, когда ICustomFormatter становится актуальным. IFormatProvider, который может предоставить тип ICustomFormatter, может быть передан как параметр IFormatProvider в таких методах, как string.Format и StringBuilder.AppendFormat.

Предоставленный ICustomFormatter имеет свой метод format для каждого форматирования, который делает string.Format. Если ICustomFormatter не знаком с используемой строкой формата или не поддерживает этот тип, он просто передает IFormattable.ToString или Object.ToString. Документация ICustomFormatter содержит список того, что необходимо, если вы форматируете объект, который еще не поддерживает форматирование, и что необходимо, если вы просто хотите добавить дополнительный формат для существующего IFormattable. Он также дает пример добавления дополнительного формата.

Ссылка

Эта страница MSDN дает отличный обзор системы форматирования .NET и предоставляет ссылки на почти все другие релевантные страницы в MSDN. Это лучшее место для начала практически любого вопроса, связанного с форматированием.

Ответ 2

Для таких вопросов хороший источник информации можно найти внутри Mono исходного кода. Скорее всего, вы найдете довольно много его использования внутри своего mscorlib.dll кода.