不错呦!smile@林凯西,确保“准备文件”中的几个文件都有安装,S...您好,看了您这篇帖子觉得很有帮助。但是有个问题想请...我的修改过了怎么还被恶意注册呢 @jjjjiiii 用PJ快9年了,主要是A...PJ3啊,貌似很少有人用PJ了,现在不是WP就是z...@332347365,我当时接入时错误码没有-10...楼主,ChkValue值应为-103是什么意思呢?...大哥 你最近能看到我发的信息,请跟我联系,我有个制...
C#格式化输出
编辑:dnawo 日期:2009-05-08
曾经一度为格式化输出而困惑,看着满天遍野的结构,都不敢去轻易触动。只能使用最安全,但是 低能的object.ToString()方法。终于忍受不了这种窘困的处境,下力气研究一番,也算是有点心得,希望和大家交流一下。
鉴于该格式化输出的结构过于繁琐,我不希望文章陷入条款的解释,于是,我从一个实际问题入手,一步一步地介绍格式化输出的概念,三个接口的意义,以及使用接口的一种模式(Pattern)。
1. PhoneNumber 类
假设我们有如下的一个类,用于存储我们的手机号码。该类提供了简单的ToString()实现,即直接返回含有短线(-)的电话号码。
2. 提供去掉短线的输出格式 (IFormattable)
现在,我们希望能输出不含有短线的电话号码。一种最简单的办法,就是提供一个属性或者方法来实现。然而,我们希望能够像以货币格式输出整数一样,能够用类似的方法,以不含有短线的方式,输出电话号码。即:
我们需要作的,就是实现IFormattable接口:
现在,一切工作的非常良好,我们的PhoneNumber类也非常顺利的发布出去了。一切看起来都非常不错!
3. 提供隐藏部分号码的输出格式 (IFormatProvider, ICustomFormatter)
在使用中,用户打电话问讯我们,能否提供隐藏部分号码的输出格式,即13908142314输出为139****2314。“这个容易,我们马上更新”,放下电话,我们在switch中加入了一项,就能解决问题。可是,这样做,一个潜在的问题是,每次我们得到新的需求,都需要修改我们的PhoneNumber类,这样做,每次用户都需要重新编译PhoneNumber类,以及所有和它相关的类,这样是一个高风险,违背软件设计原则的解决办法。于是,我们应该采用如下的模式来实现扩展的需求:
首先,实现一个单独的HideFormat类,实现两个接口。这个类就是我们自己定义的格式规则。
然后,修改我们的PhoneNumber类(只需要修改一次)。
然后,为了输出隐藏部分号码的格式。我们只需要做如下的调用:
自此,我们完成了所有的任务和更新。最后,让我们看看扩展性。如果以后我们接到了新的格式申请,我们需要作的,就是实现一个类似SecureFormat的自定义的格式类,然后交给用户使用。不需要我们修改PhoneNumber的任何实现。这个解决方案,很好的体现了开放-闭合(Open-Close Principle)的软件设计原则。
dnawo说明:原文标题为"[格式化输出] 关于IFormattable, IFormatProvider 和 ICustomFormatter的概念和使用",因本博客程序标题不允许这么多字符而修改为"C#格式化输出",望谅解!
鉴于该格式化输出的结构过于繁琐,我不希望文章陷入条款的解释,于是,我从一个实际问题入手,一步一步地介绍格式化输出的概念,三个接口的意义,以及使用接口的一种模式(Pattern)。
1. PhoneNumber 类
假设我们有如下的一个类,用于存储我们的手机号码。该类提供了简单的ToString()实现,即直接返回含有短线(-)的电话号码。
复制内容到剪贴板
程序代码

class PhoneNumber
{
private string _number = "139-0814-2314";
public PhoneNumber() { }
public PhoneNumber(string number)
{
_number = number;
}
public string Number
{
get { return _number; }
set { _number = value; }
}
public override string ToString()
{
return _number.ToString();
}
}
{
private string _number = "139-0814-2314";
public PhoneNumber() { }
public PhoneNumber(string number)
{
_number = number;
}
public string Number
{
get { return _number; }
set { _number = value; }
}
public override string ToString()
{
return _number.ToString();
}
}
2. 提供去掉短线的输出格式 (IFormattable)
现在,我们希望能输出不含有短线的电话号码。一种最简单的办法,就是提供一个属性或者方法来实现。然而,我们希望能够像以货币格式输出整数一样,能够用类似的方法,以不含有短线的方式,输出电话号码。即:
复制内容到剪贴板
程序代码

//我们通过格式字符串(formatString),可以以货币格式输出整数。
int d = 100;
string val = string.Format("{0:D}",d);
Console.WriteLine(val);
//结果是(结果会因为区域设置有不同,但结构是类似的,即在数字前会出现货币符号)
//¥100
//我们希望能够通过如下的方式,输出不含短线的电话号码。
PhoneNumber pn = new PhoneNumber();
string val = string.Format("{0:R}",pn);
Console.WriteLine(val);
//期望的结果是:
//13908142314
int d = 100;
string val = string.Format("{0:D}",d);
Console.WriteLine(val);
//结果是(结果会因为区域设置有不同,但结构是类似的,即在数字前会出现货币符号)
//¥100
//我们希望能够通过如下的方式,输出不含短线的电话号码。
PhoneNumber pn = new PhoneNumber();
string val = string.Format("{0:R}",pn);
Console.WriteLine(val);
//期望的结果是:
//13908142314
我们需要作的,就是实现IFormattable接口:
复制内容到剪贴板
程序代码

class PhoneNumber : IFormattable
{
//同上
public override string ToString()
{
return ToString(null, null);
}
//IFormattable Members
#region IFormattable Members
public string ToString(string format, IFormatProvider formatProvider)
{
string _val = string.Empty;
switch (format)
{
case "R":
_val = _number.Replace("-", "");
break;
default:
_val = _number.ToString(formatProvider);
break;
}
return _val;
}
#endregion
}
{
//同上
public override string ToString()
{
return ToString(null, null);
}
//IFormattable Members
#region IFormattable Members
public string ToString(string format, IFormatProvider formatProvider)
{
string _val = string.Empty;
switch (format)
{
case "R":
_val = _number.Replace("-", "");
break;
default:
_val = _number.ToString(formatProvider);
break;
}
return _val;
}
#endregion
}
现在,一切工作的非常良好,我们的PhoneNumber类也非常顺利的发布出去了。一切看起来都非常不错!
3. 提供隐藏部分号码的输出格式 (IFormatProvider, ICustomFormatter)
在使用中,用户打电话问讯我们,能否提供隐藏部分号码的输出格式,即13908142314输出为139****2314。“这个容易,我们马上更新”,放下电话,我们在switch中加入了一项,就能解决问题。可是,这样做,一个潜在的问题是,每次我们得到新的需求,都需要修改我们的PhoneNumber类,这样做,每次用户都需要重新编译PhoneNumber类,以及所有和它相关的类,这样是一个高风险,违背软件设计原则的解决办法。于是,我们应该采用如下的模式来实现扩展的需求:
首先,实现一个单独的HideFormat类,实现两个接口。这个类就是我们自己定义的格式规则。
复制内容到剪贴板
程序代码

class HideFormat : IFormatProvider, ICustomFormatter
{
//IFormatProvider Members
#region IFormatProvider Members
public object GetFormat(Type formatType)
{
if (typeof(ICustomFormatter) == formatType)
{
return this;
}
return null;
}
#endregion
//ICustomFormatter Members
#region ICustomFormatter Members
public string Format(string format, object arg, IFormatProvider formatProvider)
{
// Now the formatProvider must have a ICustomFormatter
if (arg == null)
{
throw new ArgumentException("The object should not be null");
}
// Describe the formatter rules here
string _val;
switch (format)
{
case "H":
_val = arg.ToString().Replace("-", "");
_val = _val.Substring(0, 3) + "****" + _val.Substring(7, 4);
break;
default:
_val = arg.ToString();
break;
}
return _val;
}
#endregion
}
{
//IFormatProvider Members
#region IFormatProvider Members
public object GetFormat(Type formatType)
{
if (typeof(ICustomFormatter) == formatType)
{
return this;
}
return null;
}
#endregion
//ICustomFormatter Members
#region ICustomFormatter Members
public string Format(string format, object arg, IFormatProvider formatProvider)
{
// Now the formatProvider must have a ICustomFormatter
if (arg == null)
{
throw new ArgumentException("The object should not be null");
}
// Describe the formatter rules here
string _val;
switch (format)
{
case "H":
_val = arg.ToString().Replace("-", "");
_val = _val.Substring(0, 3) + "****" + _val.Substring(7, 4);
break;
default:
_val = arg.ToString();
break;
}
return _val;
}
#endregion
}
然后,修改我们的PhoneNumber类(只需要修改一次)。
复制内容到剪贴板
程序代码

class PhoneNumber : IFormattable
{
//同上
//IFormattable Members
#region IFormattable Members
public string ToString(string format, IFormatProvider formatProvider)
{
string _val = string.Empty;
//如果传入的是我们自己定义的格式,则使用这个格式去处理我们的格式化请求。
if (formatProvider != null)
{
ICustomFormatter formatter = formatProvider.GetFormat(typeof(ICustomFormatter))
as ICustomFormatter;
if (null != formatter)
{
return formatter.Format(format, this, formatProvider);
}
}
//如果传入的格式为空,或者是系统默认的格式,则按照系统默认的方式去处理我们的格式化请求。
switch (format)
{
case "R":
_val = _number.Replace("-", "");
break;
default:
_val = _number.ToString(formatProvider);
break;
}
return _val;
}
#endregion
}
{
//同上
//IFormattable Members
#region IFormattable Members
public string ToString(string format, IFormatProvider formatProvider)
{
string _val = string.Empty;
//如果传入的是我们自己定义的格式,则使用这个格式去处理我们的格式化请求。
if (formatProvider != null)
{
ICustomFormatter formatter = formatProvider.GetFormat(typeof(ICustomFormatter))
as ICustomFormatter;
if (null != formatter)
{
return formatter.Format(format, this, formatProvider);
}
}
//如果传入的格式为空,或者是系统默认的格式,则按照系统默认的方式去处理我们的格式化请求。
switch (format)
{
case "R":
_val = _number.Replace("-", "");
break;
default:
_val = _number.ToString(formatProvider);
break;
}
return _val;
}
#endregion
}
然后,为了输出隐藏部分号码的格式。我们只需要做如下的调用:
复制内容到剪贴板
程序代码

PhoneNumber pn = new PhoneNumber();
SecureFormat sf = new SecureFormat();
string _val;
_val = string.Format(sf,"{0:H}", pn);
Console.WriteLine(_val); //输出结果是139****2314
_val = pn.ToString("H",sf);
Console.WriteLine(_val); //输出结果是139****2314
SecureFormat sf = new SecureFormat();
string _val;
_val = string.Format(sf,"{0:H}", pn);
Console.WriteLine(_val); //输出结果是139****2314
_val = pn.ToString("H",sf);
Console.WriteLine(_val); //输出结果是139****2314
自此,我们完成了所有的任务和更新。最后,让我们看看扩展性。如果以后我们接到了新的格式申请,我们需要作的,就是实现一个类似SecureFormat的自定义的格式类,然后交给用户使用。不需要我们修改PhoneNumber的任何实现。这个解决方案,很好的体现了开放-闭合(Open-Close Principle)的软件设计原则。
dnawo说明:原文标题为"[格式化输出] 关于IFormattable, IFormatProvider 和 ICustomFormatter的概念和使用",因本博客程序标题不允许这么多字符而修改为"C#格式化输出",望谅解!






评论: 0 | 引用: 0 | 查看次数: 4810
发表评论
请登录后再发表评论!