尝试实现自定义格式化程序,但从未调用 ICustomFormatter.Format
Trying to implement a custom formatter but ICustomFormatter.Format is never called
在遵循 Format TimeSpan in DataGridView column 如何在 DataGridView 中自定义 TimeSpan 之后,我试图弄清楚 IFormatProvider 和 ICustomFormatter 是如何工作的。我已经创建了一个完全自定义的格式化程序,它总是 returns "foo" 不管它是什么格式。
我在 Int 上使用它,但我认为它应该适用于所有类型,因为它不检查传递的值,它只是 returns "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
Format
foo
编辑: 我找到了 How to create and use a custom IFormatProvider for DateTime? and the answers there say that DateTime.ToString()
will not accept anything but DateTimeFormatInfo
or CultureInfo
and an object will be rejected if it's not of these types even if it implements ICustomFormatter
- .
所以我的问题是,这是否适用于 ToString()
方法的所有情况?它是否也适用于 DataGridView,在哪些情况下我可以传递真正的自定义格式化程序?
当您在整数上调用 ToString 并提供 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
中 return 它,因此它使用默认格式化程序(当前 cutlure)。在这种情况下使用它的有效方法如下:
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";
}
}
但我怀疑您是否可以通过这种方式 return 任意值,例如 "foo" 任何数字。
实际上 ToString() 函数接受 IFormatProvider 作为其签名的参数:
ToString(IFormatProvider)
ToString(String)
ToString(String,IFormatProvider)
而IFormatProvider只有GetFormat(Type)
的功能需要实现。 ToString()
不使用具有 Format()
功能的 ICustomFormatter
。所以
IFormatProvider
的实现是:
class MyFormatter : IFormatProvider
{
public object GetFormat(Type formatType)
{
Console.WriteLine("GetFormat");
return this;
}
}
在遵循 Format TimeSpan in DataGridView column 如何在 DataGridView 中自定义 TimeSpan 之后,我试图弄清楚 IFormatProvider 和 ICustomFormatter 是如何工作的。我已经创建了一个完全自定义的格式化程序,它总是 returns "foo" 不管它是什么格式。
我在 Int 上使用它,但我认为它应该适用于所有类型,因为它不检查传递的值,它只是 returns "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 Format foo
编辑: 我找到了 How to create and use a custom IFormatProvider for DateTime? and the answers there say that DateTime.ToString()
will not accept anything but DateTimeFormatInfo
or CultureInfo
and an object will be rejected if it's not of these types even if it implements ICustomFormatter
- .
所以我的问题是,这是否适用于 ToString()
方法的所有情况?它是否也适用于 DataGridView,在哪些情况下我可以传递真正的自定义格式化程序?
当您在整数上调用 ToString 并提供 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
中 return 它,因此它使用默认格式化程序(当前 cutlure)。在这种情况下使用它的有效方法如下:
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";
}
}
但我怀疑您是否可以通过这种方式 return 任意值,例如 "foo" 任何数字。
实际上 ToString() 函数接受 IFormatProvider 作为其签名的参数:
ToString(IFormatProvider)
ToString(String)
ToString(String,IFormatProvider)
而IFormatProvider只有GetFormat(Type)
的功能需要实现。 ToString()
不使用具有 Format()
功能的 ICustomFormatter
。所以
IFormatProvider
的实现是:
class MyFormatter : IFormatProvider
{
public object GetFormat(Type formatType)
{
Console.WriteLine("GetFormat");
return this;
}
}