IFormattable
,IFormatProvider
和ICustomFormatter
之间的区别和联系是什么?它们何时会被使用?一个简单的实现示例也非常好。
我并不是故意在.net框架中使用它,但是当我自己实现这些时,在这种情况下,哪些类通常会实现什么接口以及如何正确地执行它。
答案 0 :(得分:37)
IFormattable
是支持string.Format
格式的对象,即xxx
中的{0:xxx}
。如果对象支持该接口,string.Format
将委托给对象的IFormattable.ToString
方法。
IFormatProvider
是格式化程序用于特定于文化的日期和货币布局等配置信息的来源。
但是,对于像DateTime
,您要格式化的实例已经实现IFormattable
但您无法控制实现(BCL中提供DateTime
,您无法轻松替换它),那里是一种阻止string.Format
简单地使用IFormattable.ToString
的机制。相反,您实施IFormatProvider
,当被要求进行ICustomFormatter
实施时,请返回一个。在string.Format
委托给对象的ICustomFormatter
之前,IFormattable.Format
会检查提供商是否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")
运行时:
{{1}}
答案 1 :(得分:2)
自定义格式的工作基于三个组件之间的协调:
formattable 对象是可以通过实现IFormattable
接口使用格式提供程序和格式字符串来格式化其数据的实例。基本上,他们将请求格式提供者获取formatter
,然后使用格式字符串(这是格式指令来要求formatter
格式化其实例)。日期/时间和数字类型是格式表类型的示例。
格式提供程序是实现IFormatProvider
接口的类。他们负责根据调用者请求的格式类型返回formatter
对象。格式类型可以是格式提供者可以理解的任何类型,而返回的formatter
应该是调用者(在大多数情况下为formattable`object)可以用来格式化其数据的任何类型。
格式化程序是负责提供格式化服务的对象。对于日期/时间和数字类型,格式提供者也是formatters
,分别是CultureInfo
,DateTimeFormatInfo
和NumberFormatInfo
。
在通过诸如String.Format
,Console.WriteLine
或StringBuilder.AppendFormat
之类的某些方法实现的复合格式中,当将格式提供程序传递给他们时,他们总是向格式提供程序询问{{1 } {}实现formatter
接口。这使开发人员可以为这些方法提供各种自定义格式。
答案 2 :(得分:1)
IFormattable
是一个支持不同(命名/自定义)格式的对象 - 例如,数字等。通过使用接口,多个代码块可以使用值和格式字符串,这很常见(例如)数据绑定和string.Format
。
IFormatProvider
填补了一些与格式有关的空白 - 尤其是i18n。最常见的是,CultureInfo
用作提供者,要么提供特定的本地格式,要么使用不变文化。
据我所知,ICustomFormatter
是无关的,并且更多地与序列化(BinaryFormatter
)联系在一起。我错了......
IFormattable
对象的示例:
IFormattable d = 123.45M;
string s1 = d.ToString("c", CultureInfo.CurrentCulture), // local currency
s2 = d.ToString("c", CultureInfo.InvariantCulture); // invariant currency