Nasıl yapılır: Özel Sayısal Biçim Sağlayıcıları Tanımlama ve Kullanma

.NET, sayısal değerlerin dize gösterimi üzerinde kapsamlı denetim sağlar. Sayısal değerlerin biçimini özelleştirmek için aşağıdaki özellikleri destekler:

  • Sayıları dize gösterimine dönüştürmek için önceden tanımlanmış bir biçim kümesi sağlayan standart sayısal biçim dizeleri. Bunları parametresi Decimal.ToString(String)olan gibi herhangi bir format sayısal biçimlendirme yöntemiyle kullanabilirsiniz. Ayrıntılar için bkz . Standart Sayısal Biçim Dizeleri.

  • Özel sayısal biçim tanımlayıcılarını tanımlamak için birleştirilebilen bir simge kümesi sağlayan özel sayısal biçim dizeleri. Bunlar, Decimal.ToString(String)parametresi olan gibi herhangi bir format sayısal biçimlendirme yöntemiyle de kullanılabilir. Ayrıntılar için bkz . Özel Sayısal Biçim Dizeleri.

  • Sayısal değerlerin dize gösterimlerini görüntülerken kullanılan sembolleri ve biçim desenlerini tanımlayan özel CultureInfo veya NumberFormatInfo nesneler. Bunları parametresi ToStringolan gibi herhangi bir provider sayısal biçimlendirme yöntemiyle kullanabilirsiniz. Genellikle, provider parametre kültüre özgü biçimlendirmeyi belirtmek için kullanılır.

Bazı durumlarda (örneğin, bir uygulamanın biçimlendirilmiş bir hesap numarası, kimlik numarası veya posta kodu görüntülemesi gerektiğinde) bu üç teknik uygun olmaz. .NET ayrıca sayısal değerin nasıl biçimlendirildiğini belirlemek için ne bir CultureInfo ne de nesne olan bir NumberFormatInfo biçimlendirme nesnesi tanımlamanızı sağlar. Bu konu, böyle bir nesneyi uygulamaya yönelik adım adım yönergeleri sağlar ve telefon numaralarını biçimlendiren bir örnek sağlar.

Özel biçim sağlayıcısı tanımlama

  1. ve ICustomFormatter arabirimlerini IFormatProvider uygulayan bir sınıf tanımlayın.

  2. IFormatProvider.GetFormat yöntemini uygulayın. GetFormat , biçimlendirme yönteminin (yöntem gibi String.Format(IFormatProvider, String, Object[]) ) özel biçimlendirme gerçekleştirmekle sorumlu olan nesneyi almak için çağıran bir geri çağırma yöntemidir. tipik bir uygulaması GetFormat aşağıdakileri yapar:

    1. Yöntem parametresi olarak geçirilen nesnenin Type bir ICustomFormatter arabirimi temsil edip etmediğini belirler.

    2. parametresi arabirimi temsil ICustomFormatter ederse, GetFormat özel biçimlendirme sağlamakla sorumlu arabirimi uygulayan ICustomFormatter bir nesne döndürür. Genellikle, özel biçimlendirme nesnesi kendisini döndürür.

    3. Parametresi arabirimi temsil ICustomFormatter etmiyorsa döndürür GetFormatnull.

  3. Format yöntemini uygulayın. Bu yöntem yöntemi tarafından çağrılır String.Format(IFormatProvider, String, Object[]) ve bir sayının dize gösterimini döndürmekten sorumludur. Yöntemin uygulanması genellikle aşağıdakileri içerir:

    1. İsteğe bağlı olarak, yönteminin parametresini inceleyerek provider biçimlendirme hizmetleri sağlamaya yönelik olduğundan emin olun. hem ICustomFormatterhem de IFormatProvider uygulayan biçimlendirme nesneleri için bu, geçerli biçimlendirme nesnesiyle eşitlik için parametresini test provider etmeyi içerir.

    2. Biçimlendirme nesnesinin özel biçim tanımlayıcılarını destekleyip desteklemeyeceğini belirleyin. (Örneğin, "N" biçim belirtici, ABD telefon numarasının NANP biçiminde olması gerektiğini ve "I" ise ITU-T Önerisi E.123 biçiminde çıktıyı gösterebilir.) Biçim tanımlayıcıları kullanılıyorsa, yöntemin belirli biçim tanımlayıcısını işlemesi gerekir. parametresindeki yöntemine format geçirilir. Tanımlayıcı yoksa parametresinin format değeri olur String.Empty.

    3. yöntemine parametre olarak arg geçirilen sayısal değeri alın. Dize gösterimine dönüştürmek için gereken işlemeleri gerçekleştirin.

    4. parametresinin dize gösterimini arg döndürür.

Özel sayısal biçimlendirme nesnesi kullanma

  1. Özel biçimlendirme sınıfının yeni bir örneğini oluşturun.

  2. String.Format(IFormatProvider, String, Object[]) Özel biçimlendirme nesnesini, biçimlendirme tanımlayıcısını (veya String.Emptykullanılmadıysa) ve biçimlendirilecek sayısal değeri geçirerek biçimlendirme yöntemini çağırın.

Örnek

Aşağıdaki örnek, ABD telefon numarasını temsil eden bir sayıyı NANP veya E.123 biçimine dönüştüren adlı TelephoneFormatter özel bir sayısal biçim sağlayıcısını tanımlar. yöntemi iki biçim tanımlayıcısını işler: "N" (NANP biçimini çıkarır) ve "I" (uluslararası E.123 biçimini çıkarır).

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

Özel sayısal biçim sağlayıcısı yalnızca yöntemiyle String.Format(IFormatProvider, String, Object[]) kullanılabilir. Tümü türünde bir parametresi olan sayısal biçimlendirme yöntemlerinin diğer aşırı yüklemeleri, ToStringuygulamayı türü temsil eden bir Type nesneden NumberFormatInfo geçirirIFormatProvider.GetFormat.IFormatProvider Buna karşılık, yönteminin bir NumberFormatInfo nesnesi döndürmesini beklerler. Yoksa, özel sayısal biçim sağlayıcısı yoksayılır ve NumberFormatInfo geçerli kültürün nesnesi onun yerine kullanılır. Örnekte yöntemi, TelephoneFormatter.GetFormat yöntem parametresini inceleyerek ve dışında ICustomFormatterbir türü temsil ediyorsa döndürerek null sayısal biçimlendirme yöntemine uygunsuz bir şekilde geçirilme olasılığını işler.

Özel bir sayısal biçim sağlayıcısı biçim tanımlayıcıları kümesini destekliyorsa, yöntem çağrısında kullanılan String.Format(IFormatProvider, String, Object[]) biçim öğesinde biçim belirtici sağlanmadıysa varsayılan bir davranış sağladığınıza emin olun. Örnekte, "N" varsayılan biçim tanımlayıcısıdır. Bu, bir sayının açık biçim belirticisi sağlayarak biçimlendirilmiş bir telefon numarasına dönüştürülmesini sağlar. Aşağıdaki örnekte bu tür bir yöntem çağrısı gösterilmektedir.

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

Ancak, biçim tanımlayıcısı yoksa dönüştürmenin gerçekleşmesini de sağlar. Aşağıdaki örnekte bu tür bir yöntem çağrısı gösterilmektedir.

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

Varsayılan biçim tanımlayıcısı tanımlanmadıysa, yönteminizin uygulanması ICustomFormatter.Format aşağıdaki gibi bir kod içermelidir, böylece .NET kodunuzun desteklemediği biçimlendirmeyi sağlayabilir.

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

Bu örnekte, uygulayan ICustomFormatter.Format yöntem yöntemi için bir geri çağırma yöntemi olarak hizmet vermek üzere String.Format(IFormatProvider, String, Object[]) tasarlanmıştır. Bu nedenle, geçerli TelephoneFormatter nesneye formatProvider bir başvuru içerip içermediğini belirlemek için parametresini inceler. Ancak, yöntemi doğrudan koddan da çağrılabilir. Bu durumda, kültüre formatProvider özgü biçimlendirme bilgileri sağlayan bir CultureInfo veya NumberFormatInfo nesnesi sağlamak için parametresini kullanabilirsiniz.