C#:IFormattable、IFormatProvider和ICustomFormatter之间的连接,以及何时使用什么
C#:IFormattable、IFormatProvider和ICustomFormatter之间的连接,以及何时使用什么,c#,formatting,C#,Formatting,IFormattable、IFormatProvider和ICustomFormatter之间的区别和联系是什么,何时使用它们?一个简单的实现示例也很好 我并不是说在.net framework中何时使用它,而是指我自己何时实现这些,在这种情况下,什么类通常实现什么接口以及如何正确实现它。是一个支持不同(命名/自定义)格式的对象,例如,数字等。通过使用接口,多个代码块可以使用值和格式字符串,这在数据绑定和string.format中很常见 A填补了一些关于格式化的空白,特别是i18n。最常见的是
IFormattable
、IFormatProvider
和ICustomFormatter
之间的区别和联系是什么,何时使用它们?一个简单的实现示例也很好
我并不是说在.net framework中何时使用它,而是指我自己何时实现这些,在这种情况下,什么类通常实现什么接口以及如何正确实现它。是一个支持不同(命名/自定义)格式的对象,例如,数字等。通过使用接口,多个代码块可以使用值和格式字符串,这在数据绑定和string.format
中很常见
A填补了一些关于格式化的空白,特别是i18n。最常见的是,CultureInfo
用作提供程序,提供特定的本地格式或不变的区域性
据我所知,是不相关的,并且更多地与序列化相关(BinaryFormatter
)。我可能错了
IFormattable
对象的示例:
IFormattable d = 123.45M;
string s1 = d.ToString("c", CultureInfo.CurrentCulture), // local currency
s2 = d.ToString("c", CultureInfo.InvariantCulture); // invariant currency
是一个支持IFormattable
格式的对象,即string.Format
中的{0:xxx}
<如果对象支持该接口,则code>string.Format将委托给对象的xxx
方法IFormattable.ToString
是格式化程序用于特定于区域性的日期和货币布局等配置信息的来源IFormatProvider
- 但是,对于诸如
之类的情况,您要格式化的实例已经实现了DateTime
,但您无法控制实现(IFormattable
在BCL中提供,您无法轻松替换它),有一种机制可以防止DateTime
简单地使用string.Format
。相反,您实现了IFormattable.ToString
,当要求提供IFormatProvider
实现时,返回一个ICustomFormatter
在委托给对象的string.Format
之前,检查提供程序是否有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")
自定义格式基于3个组件之间的协调工作:
- 可格式化
- 格式提供程序
- 格式化程序
IFormattable
接口,可以使用格式提供程序和格式字符串格式化其数据的实例。基本上,他们会请求格式提供程序获取一个格式化程序
,然后使用格式字符串(即格式说明)来请求格式化程序
格式化他们的实例。日期/时间和数字类型是formattable类型的示例
格式提供程序是实现IFormatProvider
接口的类。它们负责根据调用者请求的格式类型返回格式化程序对象。格式类型可以是格式提供者可以理解的任何类型,而返回的格式化程序应该是调用者(大多数情况下是formattable`对象)可以用来格式化其数据的任何类型
格式化程序是负责提供格式化服务的对象。对于日期/时间和数字类型,格式提供程序也是格式化程序
,它们是CultureInfo
、DateTimeFormatInfo
和NumberFormatInfo
在由一些方法(如String.Format
、Console.WriteLine
或StringBuilder.AppendFormat
)实现的复合格式中,当向他们传递格式提供程序时,他们总是要求格式提供程序提供实现ICustomFormatter
接口的formatter
。这允许开发人员为这些方法提供各种自定义格式 为什么在MyFormatProvider.GetFormat
中返回CultureInfo.CurrentCulture.GetFormat
?在MyCustomFormatter.Format
中,您将如何使用IFormatProvider
?默认的格式提供程序是CultureInfo.CurrentCulture;如果在string.Format
的某个重载中未指定一个,则将使用该函数。我已经解释了您使用IFormatProvider的目的-提供配置信息(例如,询问CultureInfo)以及日期格式(例如,使用CultureInfo.DateTimeFormat)。不要在GetFormat中使用return CultureInfo.CurrentCulture.GetFormat(formatType)
,否则它会中断。最终它将被转换到ICustomFormatter中。请参阅:@Wouter每次使用CultureInfo.CurrentCulture
作为IFormatProvider
时,它都会调用GetFormat
。如果出现这种情况,那就是CultureInfo
实例的问题,因为它实现了IFormatProvider
。是否有您发现问题的特定实现?请参阅:和,了解如果要打印具有当前区域性的小数(例如,分隔符的逗号与点与小数),代码路径将如何期望IFormatProvider
(通常是CultureInfo
)支持GetFormat
)。如果之前没有为ICustomFormatter
调用GetFormat
,则无法提供CultureInfo
。这是一个非常复杂的问题