2013-01-08 43 views
11

IFormattable是否有很好的參考實現?我計劃至少爲我的對象定製一個自定義IFormatProvider,並且我要確保接線對於傳遞給IFormattable.ToString(string, IFormatProvider)的不同可能參數集合是正確的。IFormattable的參考實現

我到目前爲止有:

public class MyDataClass : IFormattable 
{ 
    /// <seealso cref="IFormattable.ToString(string, IFormatProvider)"/> 
    public string ToString(string format, IFormatProvider formatProvider) 
    { 
     ICustomFormatter formatter = (ICustomFormatter)formatProvider.GetFormat(typeof(ICustomFormatter)); 
     return formatter.Format(format, this, formatProvider); 
    } 
} 

但好像有即應該涵蓋的其他潛在的情況,:

  1. 如果formatProvider爲空,我應該回落到this.ToString()
  2. 如果formatProvider.GetFormat(typeof(ICustomFormatter))返回null,我是否應該拋出一個特殊的異常?

任何博客文章/代碼示例/ MSDN參考表示讚賞。

回答

35

您似乎誤解了.NET Framework格式化基礎架構的設計。 ICustomFormatter不應在IFormattable.ToString的實現中引用,因爲它與該接口的預期用途相沖突。

IFormattable

的對象應該只實現IFormattable如果它知道如何格式化本身(理想情況下,應該委派到另一個類的課程,但這裏會有故意耦合)。一個對象可能知道如何以多種不同的方式進行格式化,所以格式字符串允許你在它們之間進行選擇。即使如此,仍然可能會丟失信息,這些信息因文化而異。因此,有第二個參數間接提供這些信息。

傳遞給IFormatProvider.GetFormat的類型是打算成爲IFormatProvider提供給該類的特定類型或接口。

例如,內置的數字類型希望能夠檢索System.Globalization.NumberFormatInfo的實例,而DateTime相關的類希望能夠檢索System.Globalization.DateTimeFormatInfo

實施IFormattable

讓我們想象一下,我們正在創造一些新的自我格式化類。如果它只知道一種格式化的方法,它應該簡單地覆蓋object.ToString(),僅此而已。如果班級知道不止一種格式化方式應該執行IFormattable

format參數

IFormattable.ToStringthe documentation"G"格式字符串(其表示的一般格式)必須得到支持。建議將null或空格式的字符串與"G"的格式字符串等效。確切的意義在其他方面取決於我們。

formatProvider參數

如果我們需要什麼特定的文化,或否則將發生變化,我們需要利用IFormatProvider參數。我們會使用IFormatProvider.GetFormat來請求某種類型。如果IFormatProvider爲空,或者IFormatProvider.GetFormat對於我們想要的類型返回null,我們應該回退到某些默認源以獲取此不同信息。

默認來源不需要是靜態的。可以想象,默認來源可能是應用程序中的用戶設置,並且formatProvider用於預覽選項更改和/或當序列化需要固定格式時。

也有可能格式化可能涉及格式化一些子對象。在這種情況下,您可能想要通過IFormatProvider。 MSDN有一個excellent example實施IFormattable表明這種情況。

其他ToString重載

在實施IFormattable重要的是,Object.ToString()的方式相當於覆蓋以下

public override string ToString() 
{ 
    return this.ToString(null, System.Globalization.CultureInfo.CurrentCulture); 
} 

這樣做可以確保somestring + yourobject相當於string.Format("{0}{1}",somestring, yourobject),您的用戶會期望是真實的。

爲方便您的用戶,您應該提供string ToString(string format)。此外,如果您的默認格式具有可從IFormatProvider獲益的任何不同組件,您可能還需要提供public string ToString(IFormatProvider provider)

ICustomFormatter

所以,我們應該做些什麼,如果我們想格式化的一類,不知道怎麼給自己格式化,或者我們要使用不是由類本身支持的某種格式。這就是ICustomFormatter變得相關的地方。可以提供ICustomFormatter類型的IFormatProvider可以在諸如string.FormatStringBuilder.AppendFormat的方法中作爲IFormatProvider參數傳遞。

提供的ICustomFormatterstring.Format所做的每種格式都要求其Format方法。如果ICustomFormatter不熟悉所使用的格式字符串或不支持該類型,那麼它只是代表IFormattable.ToStringObject.ToString。如果您格式化尚未提供格式支持的對象,則ICustomFormatter documentation提供了所需內容的列表,如果您只想向現有的IFormattable添加額外格式,則需要什麼。它還提供了添加額外格式大小寫的例子。

參考

This MSDN page提供了.NET格式化系統的一個很好的概述,並提供鏈接到MSDN幾乎所有的其他相關網頁。這是幾乎所有與格式相關的問題開始的最佳位置。

+2

感謝您的詳細解答和參考! –

+2

當我第一次看到這個問題時,我基本上和以前一樣對所有這些都感到困惑,所以我看着反射器的框架,開始閱讀MSDN頁面,而我只是更加困惑。在我找到主要參考頁面之前,我已經閱讀了大部分MSDN頁面。即使如此,它開始點擊之前花了一段時間。有一些棘手的部分。例如,我懷疑'ICustomFormatter'與IFormatProvider一起使用的唯一原因是因爲它是1.0框架的一個晚期附加,並且他們不想添加新的'string.Format'重載。 –

0

對於這樣的問題好的來源的信息可以在Mono的源代碼裏找到。您可能會在其mscorlib.dll代碼中發現其中不少用處。