Реализация ссылок для 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);
    }
}

Но кажется, что есть другие потенциальные ситуации, которые должны быть рассмотрены, а именно:

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

Любые сообщения в блоге / примеры кода / ссылки на MSDN приветствуются.

2 ответа

Решение

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

IFormattable

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

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

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

Внедрение IFormattable

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

format параметр

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

formatProvider параметр

Если нам нужно что-то специфическое для культуры или иначе, мы должны использовать IFormatProvider параметр. Там будет какой-то тип, который мы запрашиваем с его помощью IFormatProvider.GetFormat, Если IFormatProvider является нулем, или если 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. Это лучшее место для начала практически любого вопроса, связанного с форматированием.

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

Другие вопросы по тегам