IFormattable
、IFormatProvider
和ICustomFormatter
有什么区别和联系,什么时候用?一个简单的实现示例也会非常好。
我并不是说什么时候在 .net 框架中使用它,而是什么时候我自己实现这些,在这种情况下,什么类通常会实现什么接口(interface)以及如何正确地实现它。
IFormattable
是支持string.Format
格式的对象,即{0:xxx中的xxx
}
。如果对象支持接口(interface),string.Format
将委托(delegate)给对象的 IFormattable.ToString
方法。
IFormatProvider
是格式化程序用于特定文化的日期和货币布局等配置信息的来源。
但是,对于例如DateTime
,您要格式化的实例已经实现 IFormattable
但您不控制实现(DateTime
在 BCL 中提供,您不能轻易替换),有一种机制可以防止 string.Format
简单地使用 IFormattable.ToString
。相反,您实现 IFormatProvider
,当被要求提供 ICustomFormatter
实现时,返回一个。 string.Format
在委托(delegate)给对象的 IFormattable.Format
之前检查提供程序的 ICustomFormatter
,这反过来可能会询问 IFormatProvider
用于特定于文化的数据,例如 CultureInfo
。
这是一个程序,它显示了 string.Format
向 IFormatProvider
请求什么,以及控制流程是如何进行的:
using System;
using System.Globalization;
class MyCustomObject : IFormattable
{
public string ToString(string format, IFormatProvider provider)
{
Console.WriteLine("ToString(\"{0}\", provider) called", format);
return "arbitrary value";
}
}
class MyFormatProvider : IFormatProvider
{
public object GetFormat(Type formatType)
{
Console.WriteLine("Asked for {0}", formatType);
return CultureInfo.CurrentCulture.GetFormat(formatType);
}
}
class App
{
static void Main()
{
Console.WriteLine(
string.Format(new MyFormatProvider(), "{0:foobar}",
new MyCustomObject()));
}
}
它打印这个:
Asked for System.ICustomFormatter
ToString("foobar", provider) called
arbitrary value
如果格式提供程序更改为返回自定义格式化程序,它将接管:
class MyFormatProvider : IFormatProvider
{
public object GetFormat(Type formatType)
{
Console.WriteLine("Asked for {0}", formatType);
if (formatType == typeof(ICustomFormatter))
return new MyCustomFormatter();
return CultureInfo.CurrentCulture.GetFormat(formatType);
}
}
class MyCustomFormatter : ICustomFormatter
{
public string Format(string format, object arg, IFormatProvider provider)
{
return string.Format("(format was \"{0}\")", format);
}
}
运行时:
Asked for System.ICustomFormatter
(format was "foobar")
我是一名优秀的程序员,十分优秀!