Postupy: Definování a používání vlastních poskytovatelů číselného formátu
.NET poskytuje rozsáhlou kontrolu nad řetězcovou reprezentací číselných hodnot. Podporuje následující funkce pro přizpůsobení formátu číselných hodnot:
Standardní řetězce číselného formátu, které poskytují předdefinovanou sadu formátů pro převod čísel na jejich řetězcové vyjádření. Můžete je použít s libovolnou metodou číselného formátování, například Decimal.ToString(String)s parametrem
format
. Podrobnosti najdete v tématu Standardní řetězce číselného formátu.Vlastní řetězce číselného formátu, které poskytují sadu symbolů, které lze kombinovat a definovat vlastní specifikátory číselného formátu. Lze je také použít s libovolnou metodou číselného formátování, například Decimal.ToString(String)s parametrem
format
. Podrobnosti najdete v tématu Vlastní řetězce číselného formátu.Vlastní CultureInfo objekty nebo NumberFormatInfo objekty, které definují symboly a vzory formátu použité při zobrazení řetězcových reprezentací číselných hodnot. Můžete je použít s libovolnou metodou číselného formátování, například ToStrings parametrem
provider
.provider
Parametr se obvykle používá k určení formátování specifického pro jazykovou verzi.
V některých případech (například když musí aplikace zobrazit formátované číslo účtu, identifikační číslo nebo PSČ), jsou tyto tři techniky nevhodné. Rozhraní .NET také umožňuje definovat objekt formátování, který není CultureInfo ani objektem NumberFormatInfo , abyste zjistili, jak je číselná hodnota formátována. Toto téma obsahuje podrobné pokyny k implementaci takového objektu a poskytuje příklad, který formátuje telefonní čísla.
Definování zprostředkovatele vlastního formátu
Definujte třídu, která implementuje rozhraníIFormatProvider.ICustomFormatter
Implementujte metodu IFormatProvider.GetFormat . GetFormat je metoda zpětného volání, kterou metoda formátování (například String.Format(IFormatProvider, String, Object[]) metoda) vyvolá k načtení objektu, který je ve skutečnosti zodpovědný za provádění vlastního formátování. Typická implementace GetFormat provede následující:
Určuje, zda Type objekt předaný jako parametr metody představuje ICustomFormatter rozhraní.
Pokud parametr představuje ICustomFormatter rozhraní, vrátí objekt, GetFormat který implementuje ICustomFormatter rozhraní, které je zodpovědné za poskytování vlastního formátování. Objekt vlastního formátování se obvykle vrací sám sebe.
Pokud parametr nepředstavuje ICustomFormatter rozhraní, GetFormat vrátí .
null
Implementujte metodu Format . Tato metoda je volána metodou String.Format(IFormatProvider, String, Object[]) a je zodpovědná za vrácení řetězcové reprezentace čísla. Implementace metody obvykle zahrnuje následující:
Volitelně se ujistěte, že metoda je oprávněně určena k poskytování služeb formátování prozkoumáním parametru
provider
. Pro formátování objektů, které implementují obě IFormatProvider a ICustomFormatter, to zahrnuje testováníprovider
parametr pro rovnost s aktuálním objektem formátování.Určete, zda má objekt formátování podporovat specifikátory vlastního formátu. (Například specifikátor formátu "N" může znamenat, že telefonní číslo USA by mělo být výstupem ve formátu NANP a "I" může znamenat výstup ve formátu ITU-T E.123.) Pokud se používají specifikátory formátu, měla by metoda zpracovat specifikátor konkrétního formátu. Předá se metodě v parametru
format
. Pokud není k dispozici žádný specifikátor, hodnota parametruformat
je String.Empty.Načtěte číselnou hodnotu předanou metodě jako
arg
parametr. Proveďte jakoukoli manipulaci, která je potřeba k převodu na řetězcové vyjádření.Vrátí řetězcovou reprezentaci parametru
arg
.
Použití vlastního objektu číselného formátování
Vytvořte novou instanci vlastní třídy formátování.
Zavolejte metodu String.Format(IFormatProvider, String, Object[]) formátování, předejte jí objekt vlastního formátování, specifikátor formátování (nebo String.Empty, pokud se nepoužívá) a číselnou hodnotu, kterou chcete naformátovat.
Příklad
Následující příklad definuje vlastního zprostředkovatele číselného formátu s názvem TelephoneFormatter
, který převede číslo, které představuje telefonní číslo USA, na jeho formát NANP nebo E.123. Metoda zpracovává dva specifikátory formátu, "N" (který výstupuje formát NANP) a "I" (který výstupuje mezinárodní formát E.123).
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));
}
}
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
Vlastního zprostředkovatele číselného formátu lze použít pouze s metodou String.Format(IFormatProvider, String, Object[]) . Ostatní přetížení numeric formátovací metody (například ToString
) mají parametr typu IFormatProvider všechny předat IFormatProvider.GetFormat implementaci Type objekt, který představuje NumberFormatInfo typ. Ve návratu očekávají, že metoda vrátí NumberFormatInfo objekt. Pokud tomu tak není, vlastní zprostředkovatel číselného formátu se ignoruje a NumberFormatInfo objekt aktuální jazykové verze se použije na svém místě. V příkladu TelephoneFormatter.GetFormat
metoda zpracovává možnost, že může být nevhodně předána metodě číselného formátování prozkoumáním parametru metody a vrácením null
, pokud představuje jiný typ než ICustomFormatter.
Pokud vlastní zprostředkovatel číselného formátu podporuje sadu specifikátorů formátu, ujistěte se, že jste zadali výchozí chování, pokud není v položce formátu použité ve String.Format(IFormatProvider, String, Object[]) volání metody zadán žádný specifikátor formátu. V příkladu je specifikátorem výchozího formátu "N". To umožňuje převod čísla na formátované telefonní číslo poskytnutím specifikátoru explicitního formátu. Následující příklad znázorňuje takové volání metody.
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))
Ale také umožňuje převod nastat, pokud není k dispozici žádný specifikátor formátu. Následující příklad znázorňuje 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ý specifikátor výchozího ICustomFormatter.Format formátu, vaše implementace metody by měla obsahovat kód, například následující, aby .NET mohl poskytnout formátování, které váš kód nepodporuje.
if (arg is IFormattable)
s = ((IFormattable)arg).ToString(format, formatProvider);
else if (arg != null)
s = arg.ToString();
If TypeOf (arg) Is IFormattable Then
s = DirectCast(arg, IFormattable).ToString(fmt, formatProvider)
ElseIf arg IsNot Nothing Then
s = arg.ToString()
End If
V případě tohoto příkladu je metoda, která implementuje ICustomFormatter.Format , určena jako metoda zpětného volání metody String.Format(IFormatProvider, String, Object[]) . Proto prozkoumá formatProvider
parametr, aby určil, zda obsahuje odkaz na aktuální TelephoneFormatter
objekt. Metodu však lze volat také přímo z kódu. V takovém případě můžete pomocí parametru formatProvider
CultureInfo poskytnout nebo NumberFormatInfo objekt, který poskytuje informace o formátování specifické pro jazykovou verzi.