有时候我们还要提供功能更强大的IFormattable接口来解决问题。该接口包含了一个重载的ToString()方法,它允许我们为类型指定某种格式信息。当我们需要为类型创建不同形式的字符串输出时,这个接口非常有用。

Code
1
IFormattable Members#region IFormattable Members
2
//所支持的格式:
3
//用n表示name.
4
//用r表示revenue。
5
//用p表示contact phone
6
//同时支持组合格式
7
//"G"表示通用格式
8
string System.IFormattable.ToString(string format,IFormatProvider formatProvider)
9

{
10
if(formatProvider != null)
11
{
12
ICustomFormatter fmt = formatProvider.GetFormat(this.GetType()) as ICustomFormatter;
13
if(fmt != null)
14
{
15
return fmt.Format(format,this,formatProvider);
16
}
17
}
18
switch(format)
19
{
20
case "r":
21
return _revenue.ToString();
22
case "p":
23
return _contactPhone;
24
case "nr":
25
return string.Format("{0,20},{1,10:c}",_name,_revenue);
26


27
case "n":
28
case "G":
29
default:
30
return _name;
31
}
32
}
33
#endregion添加该函数,使得Customer类型的客户可以定制Customer类型的表示:
1
IFormattable c1 = new Customer();
2
Console.WriteLine("Customer record:{0}",c1.ToString("nrp",null)); 这里需要注意的是1.必须提供通用格式"G";2.必须提供两种形式的空""和null;3.以上两点在重写时必须与Object.ToString()返回的字符串相同。
当类的使用者期望一种类的作者没有考虑到的格式,我们就要使用IFormatProvider接口啦。我们需要创建两个类:一个实现IFormatProvider接口——该类有一个方法:GetFormat(),返回一个实现了ICustomFormatter接口的对象;另一个实现ICustomFormatter接口——该类用于创建自定义的输出格式。

Code
1
//IFormatProvider示例
2
public class CustomFormatter : IFormatProvider
3

{
4
IFormatProvider Members#region IFormatProvider Members
5
//IFormatProvider仅包含一个方法。一般情况下,只有ICustomFormatter被实现。
6
public object GetFormat(Type formatType)
7
{
8
if(formatType == typeof(ICustomFormatter))
9
return new CustomFormatProvider();
10
return null;
11
}
12
#endregion
13
14
//一个嵌套类,为Customer类提供定制格式
15
private class CustomerFormatProvider : ICustomFormatter
16
{
17
ICustomFormatter Members#region ICustomFormatter Members
18
public string Format(string format,object arg,IFormatProvider formatProvider)
19
{
20
//以下为类的使用者新期望的格式,只需在此实现
21
Customer c = arg as Customer;
22
if(c == null)
23
return arg.ToString();
24
return string.Format("{0,50},{1,15},{2,10:c}",c.Name,c.ContactPhone,c.Revenue);
25
}
26
#endregion
27
}
28
}只有在极少数情况下,我们需要提供比较复杂的输出格式时,才应该实现IFormattable接口。一般只要重写ToString()方法就可以满足需要。