Procédure : définir et utiliser des fournisseurs de formats numériques personnalisés
.NET vous donne un contrôle étendu sur la représentation sous forme de chaîne de valeurs numériques. Il prend en charge les fonctionnalités suivantes pour personnaliser le format des valeurs numériques :
Chaînes de format numériques standard, qui fournissent un ensemble prédéfini de formats pour convertir des nombres dans leur représentation sous forme de chaîne. Vous pouvez les utiliser avec toute méthode de mise en forme numérique, telle que Decimal.ToString(String), qui est dotée d’un paramètre
format
. Pour plus d’informations, consultez Chaînes de format numériques standard.Chaînes de format numériques personnalisées, qui fournissent un ensemble de symboles pouvant être combinés pour définir des spécificateurs de format numériques personnalisés. Elles peuvent également être utilisées avec toute méthode de mise en forme numérique, telle que Decimal.ToString(String), qui est dotée d’un paramètre
format
. Pour plus d’informations, consultez Chaînes de format numériques personnalisées.Personnalisez les objets CultureInfo ou NumberFormatInfo, qui définissent les symboles et les modèles de format utilisés pour afficher les représentations sous forme de chaîne des valeurs numériques. Vous pouvez les utiliser avec toute méthode de mise en forme numérique, telle que ToString, qui est dotée d’un paramètre
provider
. En règle générale, le paramètreprovider
est utilisé pour spécifier une mise en forme propre à la culture.
Dans certains cas (par exemple, quand une application doit afficher un numéro de compte mis en forme, un numéro d’identification ou un code postal), ces trois techniques sont inappropriées. .NET vous permet également de définir un objet de mise en forme qui n’est ni un objet CultureInfo ni un objet NumberFormatInfo pour déterminer la mise en forme d’une valeur numérique. Cette rubrique fournit des instructions détaillées pour l’implémentation de ce type d’objet et fournit un exemple qui met en forme les numéros de téléphone.
Définir un fournisseur de format personnalisé
Définir une classe qui implémente les inferfaces IFormatProvider et ICustomFormatter.
Implémentez la méthode IFormatProvider.GetFormat. GetFormat est une méthode de rappel que la méthode de mise en forme (telle que la méthode String.Format(IFormatProvider, String, Object[])) appelle pour récupérer l’objet qui est réellement chargé d’effectuer la mise en forme personnalisée. Une implémentation type de GetFormat effectue les opérations suivantes :
Elle détermine si l’objet Type passé comme paramètre de méthode représente une interface ICustomFormatter.
Si le paramètre représente l’interface ICustomFormatter, GetFormat retourne un objet qui implémente l’interface ICustomFormatter chargée de fournir la mise en forme personnalisée. En général, l’objet de mise en forme personnalisée retourne lui-même.
Si le paramètre ne représente pas l’interface ICustomFormatter, GetFormat retourne
null
.
Implémentez la méthode Format. Cette méthode est appelée par la méthode String.Format(IFormatProvider, String, Object[]) et est chargée de retourner la représentation sous forme de chaîne d’un nombre. En général, l’implémentation de la méthode implique les étapes suivantes :
Le cas échéant, vérifiez que la méthode est légitimement destinée à fournir des services de mise en forme en examinant le paramètre
provider
. Pour les objets de mise en forme qui implémentent à la fois IFormatProvider et ICustomFormatter, vous devez déterminer si le paramètreprovider
correspond à l’objet de mise en forme actuel.Déterminez si l’objet de mise en forme doit prendre en charge les spécificateurs de format personnalisés. (Par exemple, un spécificateur de format « N » peut indiquer qu’un numéro de téléphone américain doit être au format NANP, tandis qu’un spécificateur de format « I » peut indiquer une sortie au format ITU-T Recommandation E.123.) Si des spécificateurs de format sont utilisés, la méthode doit gérer le spécificateur de format spécifique. Ill est passé à la méthode dans le paramètre
format
. Si aucun spécificateur n’est présent, la valeur du paramètreformat
est String.Empty.Récupérez la valeur numérique passée à la méthode comme paramètre
arg
. Effectuez toute opération requise pour le convertir en sa représentation sous forme de chaîne.Retournez la représentation sous forme de chaîne du paramètre
arg
.
Utiliser un objet de mise en forme numérique personnalisé
Créez une instance de la classe de mise en forme personnalisée.
Appelez la méthode de mise en forme String.Format(IFormatProvider, String, Object[]) en lui passant l’objet de mise en forme personnalisée, le spécificateur de mise en forme (ou String.Empty, si aucun n’est utilisé) et la valeur numérique à mettre en forme.
Exemple
L’exemple suivant définit un fournisseur de format numérique personnalisé nommé TelephoneFormatter
qui convertit un nombre représentant un numéro de téléphone aux États-Unis au format NANP ou E.123 correspondant. La méthode gère deux spécificateurs de format, « N » (qui génère le format NANP) et « I » (qui génère le format E.123 international).
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
Le fournisseur de format numérique personnalisé peut être utilisé uniquement avec la méthode String.Format(IFormatProvider, String, Object[]). Les autres surcharges des méthodes de mise en forme numérique (telles que ToString
) dotées d’un paramètre de type IFormatProvider passent toutes à l’implémentation IFormatProvider.GetFormat un objet Type qui représente le type NumberFormatInfo. La méthode doit normalement leur retourner un objet NumberFormatInfo. Si elle ne le fait pas, le fournisseur de format numérique personnalisé est ignoré et l’objet NumberFormatInfo pour la culture actuelle est utilisé à la place. Dans l’exemple, la méthode TelephoneFormatter.GetFormat
vérifie si la transmission à une méthode de mise en forme numérique est effectuée de façon inappropriée ; elle examine le paramètre de méthode et retourne une valeur null
si le type représenté n’est pas ICustomFormatter.
Si un fournisseur de format numérique personnalisé prend en charge un jeu de spécificateurs de format, vérifiez que vous fournissez un comportement par défaut si aucun spécificateur de format n’est fourni dans l’élément de format utilisé dans l’appel de la méthode String.Format(IFormatProvider, String, Object[]). Dans l’exemple, « N » est le spécificateur de format par défaut. Cela permet de convertir un nombre en un numéro de téléphone mis en forme en fournissant un spécificateur de format explicite. L’exemple suivant illustre un appel de méthode de ce type.
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))
Mais il permet également la conversion si aucun spécificateur de format n’est présent. L’exemple suivant illustre un appel de méthode de ce type.
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 4257884748));
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 4257884748))
Si aucun spécificateur de format par défaut n’est défini, votre implémentation de la méthode ICustomFormatter.Format doit inclure le code suivant afin que .NET puisse fournir la mise en forme que votre code ne prend pas en charge.
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
Dans le cas de cet exemple, la méthode qui implémente ICustomFormatter.Format est destinée à servir de méthode de rappel pour la méthode String.Format(IFormatProvider, String, Object[]). Ainsi, elle examine le paramètre formatProvider
pour déterminer s’il contient une référence à l’objet TelephoneFormatter
actuel. Toutefois, la méthode peut également être appelée directement à partir du code. Dans ce cas, vous pouvez utiliser le paramètre formatProvider
pour fournir un objet CultureInfo ou NumberFormatInfo qui fournit des informations de mise en forme spécifiques à la culture.