Postupy: Definování a použití poskytovatelů vlastního číselného formátu
Rozhraní .NET Framework poskytuje rozsáhlou kontrolu nad řetězcovým znázorněním číselných hodnot. Podporuje následující funkce pro vlastní nastavení formátu číselných hodnot:
Standardní numerické formátovací řetězce, které poskytují předdefinovanou sadu formátů pro převod čísel na jejich řetězcovou reprezentaci. Můžete je použít s jakoukoli metodou číselného formátování, jako například Decimal.ToString(String), která má parametr format. Detaily naleznete v tématu Standardní číselné formátovací řetězce.
Vlastní číselné formátovací řetězce, které poskytují sadu symbolů, které mohou být kombinovány pro definování vlastních specifikátorů číselného formátu. Lze je také použít s libovolnou metodou číselného formátování, jako například Decimal.ToString(String), která má parametr format. Detaily naleznete v tématu Vlastní číselné formátovací řetězce.
Vlastní objekty CultureInfo nebo NumberFormatInfo, které definují symboly a vzorky formátu použité při zobrazování řetězcových reprezentací číselných hodnot. Můžete je použít s jakoukoli metodou číselného formátování, jako například ToString, která má parametr provider. Obvykle parametr provider slouží k určení formátování specifického pro danou jazykovou verzi.
V něterých případech (například, když aplikace musí zobrazit formátované číslo účtu, identifikační číslo nebo PSČ) jsou tyto tři techniky nevhodné. Rozhraní .NET Framework také umožňuje definovat formátovací objekt, který není ani objekt CultureInfo ani NumberFormatInfo pro určení, jak je číselná hodnota formátovaná. Toto téma obsahuje podrobné pokyny pro implementaci takového objektu a poskytuje příklad, který formátuje telefonní čísla.
Chcete-li definovat vlastního poskytovatele formátu
Definujte třídu, která implementuje rozhraní IFormatProvider a ICustomFormatter.
Implementujte metodu IFormatProvider.GetFormat. GetFormat je metoda zpětného volání, kterou metoda formátování (například metoda String.Format(IFormatProvider, String, Object[])) vyvolá pro načtení objektu, který je ve skutečnosti odpovědný za provádění vlastního formátování. Typická implementace GetFormat provede následující akce:
Určí, zda objekt Type předaný jako parametr metody představuje rozhraní ICustomFormatter.
Pokud parametr představuje rozhraní ICustomFormatter, GetFormat vrátí objekt, který implementuje rozhraní ICustomFormatter, které je odpovědné za poskytování vlastního formátování. Obvykle objekt vlastního formátování vrátí sám sebe.
Pokud parametr nepředstavuje rozhraní ICustomFormatter, GetFormat vrátí null.
Implementujte metodu Format. Tato metoda je volána metodou String.Format(IFormatProvider, String, Object[]) a je odpovědná za vrácení řetězcové reprezentace čísla. Implementace metody obvykle zahrnuje následující:
Volitelně se ujistěte, že je metoda oprávněna k poskytování služeb formátování ověřením parametru provider. Pro objekty formátu, které implementují IFormatProvider i ICustomFormatter to zahrnuje testování parametru provider na rovnost s aktuálním objektem formátování.
Zjistěte, zda by měl objekt formátování podporovat vlastní specifikátory formátu. (Například specifikátor formátu N může označovat, že by telefonní číslo pro USA mělo být ve formátu NANP pro výstup a I může znamenat, že by výstup měl být ve formátu E.123 doporučení ITU-T.) Pokud jsou použity specifikátory formátu, měla by metoda zpracovávat příslušný specifikátor formátu. Je předán metodě v parametru format. Není-li nastaven žádný specifikátor, hodnota parametru format je String.Empty.
Načtěte číselnou hodnotu předanou metodě jako parametr arg. Proveďte jakékoli požadované manipulace pro převod na jeho řetězcovou reprezentaci.
Vraťte řetězcové vyjádření parametru arg.
Chcete-li použít vlastní objekt číselného formátování
Vytvořte novou instanci vlastní třídy formátování.
Volejte metodu formátování String.Format(IFormatProvider, String, Object[]), předejte jí vlastní objekt formátování, specifikátor formátu (nebo String.Empty, pokud není žádný použitý) a číselnou hodnotu, která má být formátována.
Příklad
Následující příklad definuje vlastního poskytovatele číselného formátu s názvem TelephoneFormatter, který převádí číslo představující telefonní číslo v USA do formátu NANP nebo E.123. Metoda zpracovává dva specifikátory formátu N (který poskytuje výstup ve formátu NANP) a I (který poskytuje výstup v mezinárodním formátu E.123).
Public Class TelephoneFormatter : Implements IFormatProvider, ICustomFormatter
Public Function GetFormat(formatType As Type) As Object _
Implements IFormatProvider.GetFormat
If formatType Is GetType(ICustomFormatter) Then
Return Me
Else
Return Nothing
End If
End Function
Public Function Format(fmt As String, arg As Object, _
formatProvider As IFormatProvider) As String _
Implements ICustomFormatter.Format
' Check whether this is an appropriate callback
If Not Me.Equals(formatProvider) Then Return Nothing
' Set default format specifier
If String.IsNullOrEmpty(fmt) Then fmt = "N"
Dim numericString As String = arg.ToString
If fmt = "N" Then
Select Case numericString.Length
Case <= 4
Return numericString
Case 7
Return Left(numericString, 3) & "-" & Mid(numericString, 4)
Case 10
Return "(" & Left(numericString, 3) & ") " & _
Mid(numericString, 4, 3) & "-" & Mid(numericString, 7)
Case Else
Throw New FormatException( _
String.Format("'{0}' cannot be used to format {1}.", _
fmt, arg.ToString()))
End Select
ElseIf fmt = "I" Then
If numericString.Length < 10 Then
Throw New FormatException(String.Format("{0} does not have 10 digits.", arg.ToString()))
Else
numericString = "+1 " & Left(numericString, 3) & " " & Mid(numericString, 4, 3) & " " & Mid(numericString, 7)
End If
Else
Throw New FormatException(String.Format("The {0} format specifier is invalid.", fmt))
End If
Return numericString
End Function
End Class
Public Module TestTelephoneFormatter
Public Sub Main
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 0))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 911))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 8490216))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 4257884748))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 0))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 911))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 8490216))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:I}", 4257884748))
End Sub
End Module
using System;
using System.Globalization;
public class TelephoneFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
// Check whether this is an appropriate callback
if (! this.Equals(formatProvider))
return null;
// Set default format specifier
if (string.IsNullOrEmpty(format))
format = "N";
string numericString = arg.ToString();
if (format == "N")
{
if (numericString.Length <= 4)
return numericString;
else if (numericString.Length == 7)
return numericString.Substring(0, 3) + "-" + numericString.Substring(3, 4);
else if (numericString.Length == 10)
return "(" + numericString.Substring(0, 3) + ") " +
numericString.Substring(3, 3) + "-" + numericString.Substring(6);
else
throw new FormatException(
string.Format("'{0}' cannot be used to format {1}.",
format, arg.ToString()));
}
else if (format == "I")
{
if (numericString.Length < 10)
throw new FormatException(string.Format("{0} does not have 10 digits.", arg.ToString()));
else
numericString = "+1 " + numericString.Substring(0, 3) + " " + numericString.Substring(3, 3) + " " + numericString.Substring(6);
}
else
{
throw new FormatException(string.Format("The {0} format specifier is invalid.", format));
}
return numericString;
}
}
public class TestTelephoneFormatter
{
public static void Main()
{
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 0));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 911));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 8490216));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 4257884748));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 0));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 911));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 8490216));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:I}", 4257884748));
}
}
Poskytovatel vlastního číselného formátu lze použít pouze s metodou String.Format(IFormatProvider, String, Object[]). Další přetížení číselných formátovacích metod (například ToString), které mají parametr typu IFormatProvider předávají implementaci IFormatProvider.GetFormat objekt Type, který představuje typ NumberFormatInfo. Je očekáváno, že metoda vrátí objekt NumberFormatInfo. Pokud ne, poskytovatel vlastního číselného formátu je ignorován a objekt NumberFormatInfo pro aktuální jazykovou verzi je použitý místo něj. V příkladu metoda TelephoneFormatter.GetFormat zpracovává případ, že by mohl být nevhodně předán metodě číselného fomátování kontrolou parametru metody a vrácení null pokud představuje jiný typ než ICustomFormatter.
Pokud vlastní poskytovatel číselného formátu podporuje sadu specifikátorů formátu, ujistěte se, že zadáte výchozí chování, jestliže není zadán žádný specifikátor formátu v položce formátu použité při volání metody String.Format(IFormatProvider, String, Object[]). V příkladu je výchozím specifikátorem formátu N. To umožňuje číslu, aby bylo převedeno na formátované telefonní číslo poskytnutím explicitního specifikátoru formátu. Následující příklad ukazuje takové volání metody.
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));
Ale umožňuje také, aby došlo ke konverzi v případě, že není zadán žádný specifikátor formátu. Následující příklad ukazuje takové volání metody.
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 4257884748))
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 4257884748));
Pokud není definován žádný výchozí specifikátor formátu, měla by vaše implementace metody ICustomFormatter.Format obsahovat kód jako je následující kód, aby rozhraní .NET Framework mohlo poskytnout formátování, které není podporováno vašim kódem.
If TypeOf(arg) Is IFormattable Then
s = DirectCast(arg, IFormattable).ToString(fmt, formatProvider)
ElseIf arg IsNot Nothing Then
s = arg.ToString()
End If
if (arg is IFormattable)
s = ((IFormattable)arg).ToString(format, formatProvider);
else if (arg != null)
s = arg.ToString();
V případě tohoto příkladu metoda, která implementuje ICustomFormatter.Format je zamýšlena jako metoda pro zpětné volání metody String.Format(IFormatProvider, String, Object[]). Proto zkontroluje parametr formatProvider, aby určila, zda obsahuje odkaz na aktuální objekt TelephoneFormatter. Metoda však může být také volána přímo z kódu. V takovém případě můžete použít parametr formatProvider pro poskytnutí objektu CultureInfo nebo NumberFormatInfo, který poskytuje informace o formátování specifické pro jazykovou verzi.
Probíhá kompilace kódu
Kompilujte kód v příkazovém řádku pomocí csc.exe nebo vb.exe. Pro kompilaci kódu ve Visual Studio, vložte kód do šablony projektu pro konzolové aplikace.