2009-11-08 7 views

Odpowiedz

32
  • IFormattable jest obiektem, który obsługuje formaty w string.Format, tj xxx w {0:xxx}. string.Format będzie delegować do metody obiektu IFormattable.ToString, jeśli obiekt obsługuje interfejs.

  • IFormatProvider to źródło informacji konfiguracyjnych, które są przydatne w takich formułkach, jak układ daty i waluty zależny od kultury.

  • Jednak w sytuacjach takich jak np. DateTime, gdzie instancja, którą chcesz sformatować, już implementuje IFormattable, ale nie kontrolujesz implementacji (DateTime jest dostarczany w BCL, nie można go łatwo zastąpić), istnieje mechanizm, który zapobiega używaniu string.Format po prostu przy użyciu IFormattable.ToString. Zamiast tego implementujesz IFormatProvider, a gdy zostaniesz zapytany o implementację ICustomFormatter, zwróć jeden. string.Format sprawdza dostawcę pod kątem ICustomFormatter, zanim przekaże go do obiektu IFormattable.Format, co z kolei prawdopodobnie poprosi o IFormatProvider dla danych specyficznych dla kultury, takich jak CultureInfo.

Oto program, który pokazuje, co string.Format prosi IFormatProvider dla i jak przepływ sterowania idzie:

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())); 
    } 
} 

Drukuje to:

Asked for System.ICustomFormatter 
ToString("foobar", provider) called 
arbitrary value 

Jeśli dostawca Format zostanie zmieniony w celu zwrócenia niestandardowego formatyzatora, przejmie:

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); 
    } 
} 

Kiedy run:

Asked for System.ICustomFormatter 
(format was "foobar") 
+0

Dlaczego zwracasz 'CultureInfo.CurrentCulture.GetFormat' w' MyFormatProvider.GetFormat'? A co byś użył '' IFormatProvider' dla '' MyCustomFormatter.Format'? – Svish

+0

Domyślnym dostawcą formatu jest CultureInfo.CurrentCulture; to jest ten, który jest używany, jeśli nie określisz jednego z przeciążeń do 'string.Format'. Już wyjaśniłem, do czego użyłbyś IFormatProvider - aby podać informacje o konfiguracji (np. Poprosić o CultureInfo), o takie rzeczy jak formatowanie daty (np. Użycie CultureInfo.DateTimeFormat). –

1

IFormattable to obiekt obsługujący różne (nazwane/niestandardowe) formaty - na przykład liczby itp. Za pomocą interfejsu wiele bloków kodu może korzystać z wartości i ciągu formatów, co jest powszechne (np.) w wiązaniu danych i string.Format.

An IFormatProvider wypełnia luki dotyczące formatowania - szczególnie i18n. Najczęściej jako dostawcę używany jest CultureInfo, który podaje konkretny format lokalny lub kulturę niezmienniczą.

O ile mi wiadomo, ICustomFormatter nie ma związku i wiąże się bardziej z serializacją (BinaryFormatter). Mogę się mylić ...

Przykładem obiektu IFormattable:

IFormattable d = 123.45M; 
string s1 = d.ToString("c", CultureInfo.CurrentCulture), // local currency 
     s2 = d.ToString("c", CultureInfo.InvariantCulture); // invariant currency 
+2

Jest to bardzo stary odpowiedź, ale w trosce o dzieci: 'ICustomFormatter' jest rzeczywiście o formatowanie ciąg, a za dodanie wsparcia dla formatu ciągi do typów, które nie są' IFormattable' implementations (lub do dostarczania różnych ciągów formatów do obiektów 'IFormattable'). 'IFormatter' to ten o serializacji. –