Share via


Comment : définir et utiliser des fournisseurs de format numérique personnalisés

Mise à jour : novembre 2007

Le .NET Framework vous permet de contrôler la représentation sous forme de chaîne de valeurs numériques. Les fonctionnalités suivantes sont prises en charge pour personnaliser le format des valeurs numériques :

  • Chaînes de format numérique standard qui fournissent un jeu 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 possède un paramètre format. Pour plus d'informations, consultez Chaînes de format numériques standard.

  • Chaînes de format numérique personnalisées qui fournissent un jeu des symboles pouvant être combinés pour définir des spécificateurs de format numérique personnalisés. Vous pouvez également les utiliser avec toute méthode de mise en forme numérique, telle que Decimal.ToString(String), qui possède un paramètre format. Pour plus d'informations, consultez Chaînes de format numériques personnalisées.

  • Objets CultureInfo ou NumberFormatInfo personnalisés qui définissent les symboles et modèles de format utilisés pour afficher les représentations sous forme de chaîne de valeurs numériques. Vous pouvez les utiliser avec toute méthode de mise en forme numérique, telle que ToString, qui possède un paramètre provider. En général, le paramètre provider est utilisé pour spécifier une mise en forme spécifique à la culture.

Dans certains cas (par exemple, lorsqu'une application doit afficher un numéro de compte mis en forme, un numéro d'identification ou un code postal), ces trois techniques ne sont pas appropriées. Le .NET Framework 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 comment une valeur numérique est mise en forme. Cette rubrique fournit des instructions pas à pas pour implémenter ce type d'objet et propose un exemple de mise en forme de numéros de téléphone.

Pour définir un fournisseur de format personnalisé

  1. Définissez une classe qui implémente les interfaces IFormatProvider et ICustomFormatter.

  2. Implémentez la méthode IFormatProvider.GetFormat. GetFormat est une méthode de rappel que la méthode de mise en forme (comme la méthode String.Format(IFormatProvider, String, array<Object[])) appelle pour récupérer l'objet chargé d'effectuer la mise en forme personnalisée. En général, l'implémentation de GetFormat donne les résultats suivants :

    1. Détermine si l'objet Type passé comme paramètre de méthode représente une interface ICustomFormatter.

    2. 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 se retourne lui-même.

    3. Si le paramètre ne représente pas l'interface ICustomFormatter, GetFormat retourne null.

  3. Implémentez la méthode Format. Cette méthode appelée par String.Format(IFormatProvider, String, array<Object[]) est chargée de retourner la représentation sous forme de chaîne d'un nombre. L'implémentation de la méthode implique généralement ce qui suit :

    1. Si vous le souhaitez, assurez-vous que la méthode est légitimement destinée à fournir des services de mise en forme en examinant le paramètre provider. Pour mettre en forme des objets qui implémentent IFormatProvider et ICustomFormatter, vous devez tester l'égalité du paramètre provider avec l'objet de mise en forme actuel.

    2. Déterminez si l'objet de mise en forme doit prendre en charge des spécificateurs de format personnalisés. Par exemple, un spécificateur de format "N" peut indiquer un numéro de téléphone américain affiché au format NANP et un spécificateur "I" peut indiquer un résultat affiché au format spécifié par la Recommandation E.123 de l'UIT-T. Si les spécificateurs de format sont utilisés, la méthode doit gérer le spécificateur de format spécifique. Il est passé à la méthode dans le paramètre format. Si aucun spécificateur n'est présent, la valeur du paramètre format est String.Empty.

    3. Récupérez la valeur numérique passée à la méthode comme paramètre arg. Effectuez les opérations requises pour procéder à sa conversion sous forme de chaîne.

    4. Retournez la représentation sous forme de chaîne du paramètre arg.

Pour utiliser un objet de mise en forme numérique personnalisé

  1. Créez une nouvelle instance de la classe de mise en forme personnalisée.

  2. Appelez la méthode de mise en forme String.Format(IFormatProvider, String, array<Object[]) en lui passant l'objet de mise en forme personnalisée, le spécificateur de mise en forme (ou String.Empty si aucun spécificateur 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 américain au format NANP ou E.123. La méthode gère deux spécificateurs de format : "N" (résultat affiché au format NANP) et "I" (résultat affiché au format E.123 international).

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

Le fournisseur de format numérique personnalisé ne peut être utilisé qu'avec la méthode String.Format(IFormatProvider, String, array<Object[]). Les autres surcharges des méthodes de mise en forme numériques (telles que ToString) qui possèdent un paramètre de type IFormatProvider passent toutes à l'implémentation IFormatProvider.GetFormat un objet Type représentant le type NumberFormatInfo. Normalement, la méthode doit retourner un objet NumberFormatInfo. Si ce n'est pas le cas, le fournisseur de format numérique personnalisé est ignoré et l'objet NumberFormatInfo de la culture actuelle est utilisé à la place. Dans l'exemple, si l'objet n'a pas été correctement passé à une méthode de mise en forme numérique, la méthode TelephoneFormatter.GetFormat examine le paramètre de méthode et retourne null s'il représente un type autre que ICustomFormatter.

Si un fournisseur de format numérique personnalisé prend en charge un jeu de spécificateurs de format, n'oubliez pas de spécifier 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 méthode String.Format(IFormatProvider, String, array<Object[]). Dans l'exemple, "N" est le spécificateur de format par défaut. Ainsi, en fournissant un spécificateur de format explicite, vous pouvez convertir un nombre en un numéro de téléphone mis en forme. L'exemple suivant illustre ce type d'appel de méthode.

Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))
Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));

La conversion est également possible si aucun spécificateur de format n'est présent. L'exemple suivant illustre ce type d'appel de méthode.

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 du code tel que le suivant afin que le .NET Framework puisse fournir une mise en forme non prise en charge par votre code.

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

Dans cet exemple, la méthode qui implémente ICustomFormatter.Format doit normalement servir de méthode de rappel pour la méthode String.Format(IFormatProvider, String, array<Object[]). Par conséquent, 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 du code. Dans ce cas, vous pouvez utiliser le paramètre formatProvider pour fournir un objet CultureInfo ou NumberFormatInfo qui apporte des informations de mise en forme spécifiques à la culture.

Compilation du code

Compilez le code sur la ligne de commande à l'aide de csc.exe ou vb.exe. Pour compiler le code dans Visual Studio, placez-le dans un modèle de projet d'application console.

Voir aussi

Concepts

Rubriques Comment relatives à la mise en forme