Попытка реализовать собственный форматировщик, но ICustomFormatter.Format никогда не вызывается
Я пытаюсь выяснить, как IFormatProvider и ICustomFormatter работают после следующего форматирования TimeSpan в столбце DataGridView о том, как настроить TimeSpan в DataGridView. Я создал полностью собственный форматтер, который всегда возвращает "foo" независимо от того, что он форматирует.
Я использую его на Int, но я предполагаю, что он должен работать на всех типах, так как он не проверяет передаваемое значение, он просто возвращает "foo"
,
class MyFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
Console.WriteLine("GetFormat");
return this;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
Console.WriteLine("Format");
return "foo";
}
}
И я передаю это int.ToString()
:
int number = 10;
Console.WriteLine(number.ToString(new MyFormatter()));
Что я получаю это:
GetFormat 10
В то время как я надеялся получить это:
GetFormat Формат Foo
Изменить: я нашел Как создать и использовать пользовательский IFormatProvider для DateTime? и ответы там говорят, что DateTime.ToString()
не примет ничего, кроме DateTimeFormatInfo
или же CultureInfo
и объект будет отклонен, если он не относится к этим типам, даже если он реализует ICustomFormatter
- /questions/17696832/kak-sozdat-i-ispolzovat-polzovatelskij-iformatprovider-dlya-datetime/17696836#17696836.
Поэтому мой вопрос заключается в том, имеет ли это место во всех случаях ToString()
методы? Это относится и к DataGridView, и в каких случаях я могу передать действительно специальный форматтер?
2 ответа
Когда вы вызываете ToString для integer и предоставляете IFormatProvider, он будет пытаться извлечь NumberFormatInfo из него примерно следующим образом:
public static NumberFormatInfo GetInstance(IFormatProvider formatProvider)
{
CultureInfo cultureInfo = formatProvider as CultureInfo;
if (cultureInfo != null && !cultureInfo.m_isInherited)
return cultureInfo.numInfo ?? cultureInfo.NumberFormat;
NumberFormatInfo numberFormatInfo = formatProvider as NumberFormatInfo;
if (numberFormatInfo != null)
return numberFormatInfo;
if (formatProvider != null)
{
NumberFormatInfo format = formatProvider.GetFormat(typeof (NumberFormatInfo)) as NumberFormatInfo;
if (format != null)
return format;
}
return NumberFormatInfo.CurrentInfo;
}
Итак, вы видите, если все остальное терпит неудачу, это вызывает GetFormat
с типом, равным NumberFormatInfo
и ожидает NumberFormatInfo
назад. Вы не вернете это из GetFormat
, так что вместо него используется форматтер по умолчанию (текущая режущая кромка). Так что правильным способом использовать его в этом случае будет что-то вроде:
class MyFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(NumberFormatInfo)) {
return new NumberFormatInfo()
{
// something here
};
}
Console.WriteLine("GetFormat");
return this;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
Console.WriteLine("Format");
return "foo";
}
}
Но, таким образом, я сомневаюсь, что вы можете вернуть произвольные значения, такие как "foo" для любого числа.
На самом деле функция ToString() принимает IFormatProvider в качестве аргумента, его подпись гласит:
ToString(IFormatProvider)
ToString(String)
ToString(String,IFormatProvider)
и IFormatProvider имеет только GetFormat(Type)
Функция для реализации. ToString()
не использует ICustomFormatter
который имеет Format()
функция. Таким образом, реализация для IFormatProvider
является:
class MyFormatter : IFormatProvider
{
public object GetFormat(Type formatType)
{
Console.WriteLine("GetFormat");
return this;
}
}