ICustomFormatter ICustomFormatter ICustomFormatter ICustomFormatter Interface

定义

定义一种方法,它支持自定义设置对象的值的格式。Defines a method that supports custom formatting of the value of an object.

public interface class ICustomFormatter
[System.Runtime.InteropServices.ComVisible(true)]
public interface ICustomFormatter
type ICustomFormatter = interface
Public Interface ICustomFormatter
属性

示例

下面的示例实现ICustomFormatter , 以允许整数值的二进制、八进制和十六进制格式设置。The following example implements ICustomFormatter to allow binary, octal, and hexadecimal formatting of integral values. 在此示例中, 单个类IBinaryFormatter ICustomFormatter实现和IFormatProviderIn this example, a single class, IBinaryFormatter, implements both ICustomFormatter and IFormatProvider. IFormatProvider.GetFormat方法确定formatType参数是否表示ICustomFormatter类型。Its IFormatProvider.GetFormat method determines whether the formatType parameter represents an ICustomFormatter type. 如果它存在, BinaryFormatter则返回自身的实例; 否则返回。 nullIf it does, BinaryFormatter returns an instance of itself; otherwise, it returns null. ICustomFormatter.Format实现确定 format 参数是否为三个受支持的格式字符串之一 (二进制的 "B"、八进制的 "O" 和十六进制的 "H"), 并适当设置arg参数的格式。Its ICustomFormatter.Format implementation determines whether the format parameter is one of the three supported format strings ("B" for binary, "O" for octal, and "H" for hexadecimal) and formats the arg parameter appropriately. 否则, 如果argnull是, 它将调用arg参数的IFormattable.ToString实现 (如果存在) 或它的无ToString参数方法 (如果不存在)。Otherwise, if arg is not null, it calls the arg parameter's IFormattable.ToString implementation, if one exists, or its parameterless ToString method, if one does not. 如果 argnull,则此方法返回 String.EmptyIf arg is null, the method returns String.Empty.

using System;
using System.Globalization;
using System.Numerics;

public class BinaryFormatter : IFormatProvider, ICustomFormatter
{
   // IFormatProvider.GetFormat implementation.
   public object GetFormat(Type formatType)
   {
      // Determine whether custom formatting object is requested.
      if (formatType == typeof(ICustomFormatter))
         return this;
      else
         return null;
   }   

   // Format number in binary (B), octal (O), or hexadecimal (H).
   public string Format(string format, object arg, IFormatProvider formatProvider)
   {
      // Handle format string.
      int baseNumber;
      // Handle null or empty format string, string with precision specifier.
      string thisFmt = String.Empty;
      // Extract first character of format string (precision specifiers
      // are not supported).
      if (! String.IsNullOrEmpty(format))
         thisFmt = format.Length > 1 ? format.Substring(0, 1) : format;
         

      // Get a byte array representing the numeric value.
      byte[] bytes;
      if (arg is sbyte)
      {
         string byteString = ((sbyte) arg).ToString("X2");
         bytes = new byte[1] { Byte.Parse(byteString, System.Globalization.NumberStyles.HexNumber ) };
      }
      else if (arg is byte) {
         bytes = new byte[1] { (byte) arg };
      }   
      else if (arg is short) {
         bytes = BitConverter.GetBytes((short) arg);
      }   
      else if (arg is int) {
         bytes = BitConverter.GetBytes((int) arg);
      }   
      else if (arg is long) {
         bytes = BitConverter.GetBytes((long) arg);
      }
      else if (arg is ushort) {
         bytes = BitConverter.GetBytes((ushort) arg);
      }
      else if (arg is uint) {
         bytes = BitConverter.GetBytes((uint) arg);
      }
      else if (arg is ulong) {
         bytes = BitConverter.GetBytes((ulong) arg);                  
      }
      else if (arg is BigInteger) {
         bytes = ((BigInteger) arg).ToByteArray();
      }
      else {
         try {
            return HandleOtherFormats(format, arg); 
         }
         catch (FormatException e) {
            throw new FormatException(String.Format("The format of '{0}' is invalid.", format), e);
         }
      }

      switch (thisFmt.ToUpper())
      {
         // Binary formatting.
         case "B":
            baseNumber = 2;
            break;        
         case "O":
            baseNumber = 8;
            break;
         case "H":
            baseNumber = 16;
            break;
         // Handle unsupported format strings.
         default:
         try {
            return HandleOtherFormats(format, arg); 
         }
         catch (FormatException e) {
            throw new FormatException(String.Format("The format of '{0}' is invalid.", format), e);
         }
      }
   
      // Return a formatted string.
      string numericString = String.Empty;
      for (int ctr = bytes.GetUpperBound(0); ctr >= bytes.GetLowerBound(0); ctr--)
      {
         string byteString = Convert.ToString(bytes[ctr], baseNumber);
         if (baseNumber == 2)
            byteString = new String('0', 8 - byteString.Length) + byteString;
         else if (baseNumber == 8)
            byteString = new String('0', 4 - byteString.Length) + byteString;
         // Base is 16.
         else     
            byteString = new String('0', 2 - byteString.Length) + byteString;

         numericString +=  byteString + " ";
      }
      return numericString.Trim();
   }

   private string HandleOtherFormats(string format, object arg)
   {
      if (arg is IFormattable) 
         return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
      else if (arg != null)
         return arg.ToString();
      else
         return String.Empty;
   }
}
Imports System.Globalization
Imports System.Numerics

Public Class BinaryFormatter : Implements IFormatProvider, ICustomFormatter
   ' IFormatProvider.GetFormat implementation.
   Public Function GetFormat(formatType As Type) As Object _
                   Implements IFormatProvider.GetFormat
      ' Determine whether custom formatting object is requested.
      If formatType Is GetType(ICustomFormatter) Then
         Return Me
      Else
         Return Nothing
      End If
   End Function   

   ' Format number in binary (B), octal (O), or hexadecimal (H).
   Public Function Format(fmt As String, arg As Object, _
                          formatProvider As IFormatProvider) As String _
                   Implements ICustomFormatter.Format

     ' Handle format string.
      Dim base As Integer
      ' Handle null or empty format string, string with precision specifier.
      Dim thisFmt As String = String.Empty
      ' Extract first character of format string (precision specifiers
      ' are not supported by BinaryFormatter).
      If Not String.IsNullOrEmpty(fmt) Then
         thisFmt = CStr(IIf(fmt.Length > 1, fmt.Substring(0, 1), fmt))
      End If
         


      ' Get a byte array representing the numeric value.
      Dim bytes() As Byte
      If TypeOf(arg) Is SByte Then
         Dim byteString As String = CType(arg, SByte).ToString("X2")
         bytes = New Byte(0) { Byte.Parse(byteString, System.Globalization.NumberStyles.HexNumber ) }
      ElseIf TypeOf(arg) Is Byte Then
         bytes = New Byte(0) { CType(arg, Byte) }
      ElseIf TypeOf(arg) Is Int16 Then
         bytes = BitConverter.GetBytes(CType(arg, Int16))
      ElseIf TypeOf(arg) Is Int32 Then
         bytes = BitConverter.GetBytes(CType(arg, Int32))
      ElseIf TypeOf(arg) Is Int64 Then
         bytes = BitConverter.GetBytes(CType(arg, Int64))
      ElseIf TypeOf(arg) Is UInt16 Then
         bytes = BitConverter.GetBytes(CType(arg, UInt16))
      ElseIf TypeOf(arg) Is UInt32 Then
         bytes = BitConverter.GetBytes(CType(arg, UInt64))
      ElseIf TypeOf(arg) Is UInt64 Then
         bytes = BitConverter.GetBytes(CType(arg, UInt64))                  
      ElseIf TypeOf(arg) Is BigInteger Then
         bytes = CType(arg, BigInteger).ToByteArray()
      Else
         Try 
            Return HandleOtherFormats(fmt, arg) 
         Catch e As FormatException 
            Throw New FormatException(String.Format("The format of '{0}' is invalid.", fmt), e)
         End Try
      End If

      Select Case thisFmt.ToUpper()
         ' Binary formatting.
         Case "B"
            base = 2        
         Case "O"
            base = 8
         Case "H"
            base = 16
         ' Handle unsupported format strings.
         Case Else
            Try 
               Return HandleOtherFormats(fmt, arg) 
            Catch e As FormatException 
               Throw New FormatException(String.Format("The format of '{0}' is invalid.", fmt), e)
            End Try
      End Select
      
      ' Return a formatted string.
      Dim numericString As String = String.Empty
      For ctr As Integer = bytes.GetUpperBound(0) To bytes.GetLowerBound(0) Step -1
         Dim byteString As String = Convert.ToString(bytes(ctr), base)
         If base = 2 Then
            byteString = New String("0"c, 8 - byteString.Length) + byteString
         ElseIf base = 8 Then
            byteString = New String("0"c, 4 - byteString.Length) + byteString
         ' Base is 16.
         Else     
            byteString = New String("0"c, 2 - byteString.Length) + byteString
         End If
         numericString +=  byteString + " "
      Next
      Return numericString.Trim()
   End Function
   
   Private Function HandleOtherFormats(fmt As String, arg As Object) As String
      If TypeOf arg Is IFormattable Then
         Return DirectCast(arg, IFormattable).ToString(fmt, CultureInfo.CurrentCulture)
      ElseIf arg IsNot Nothing Then
         Return arg.ToString()
      Else
         Return String.Empty
      End If
   End Function
End Class

BinaryFormatter然后, 可以使用将BinaryFormatter对象provider作为Format方法的参数传递来提供自定义格式设置, 如下面的示例所示。BinaryFormatter can then be used to provide custom formatting by passing a BinaryFormatter object as the provider parameter of the Format method, as the following example shows.

public class Example
{
   public static void Main()
   {
      Console.WindowWidth = 100;
      
      byte byteValue = 124;
      Console.WriteLine(String.Format(new BinaryFormatter(), 
                                      "{0} (binary: {0:B}) (hex: {0:H})", byteValue));
      
      int intValue = 23045;
      Console.WriteLine(String.Format(new BinaryFormatter(), 
                                      "{0} (binary: {0:B}) (hex: {0:H})", intValue));
      
      ulong ulngValue = 31906574882;
      Console.WriteLine(String.Format(new BinaryFormatter(), 
                                      "{0}\n   (binary: {0:B})\n   (hex: {0:H})", 
                                      ulngValue));

      BigInteger bigIntValue = BigInteger.Multiply(Int64.MaxValue, 2);
      Console.WriteLine(String.Format(new BinaryFormatter(), 
                                      "{0}\n   (binary: {0:B})\n   (hex: {0:H})", 
                                      bigIntValue));
   }
}
// The example displays the following output:
//    124 (binary: 01111100) (hex: 7c)
//    23045 (binary: 00000000 00000000 01011010 00000101) (hex: 00 00 5a 05)
//    31906574882
//       (binary: 00000000 00000000 00000000 00000111 01101101 11000111 10110010 00100010)
//       (hex: 00 00 00 07 6d c7 b2 22)
//    18446744073709551614
//       (binary: 00000000 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110)
//       (hex: 00 ff ff ff ff ff ff ff fe)
Public Module Example
   Public Sub Main
      Console.WindowWidth = 100
      
      Dim byteValue As Byte = 124
      Console.WriteLine(String.Format(New BinaryFormatter(), _
                                      "{0} (binary: {0:B}) (hex: {0:H})", byteValue))
      
      Dim intValue As Integer = 23045
      Console.WriteLine(String.Format(New BinaryFormatter(), _
                                      "{0} (binary: {0:B}) (hex: {0:H})", intValue))
      
      Dim ulngValue As ULong = 31906574882
      Console.WriteLine(String.Format(New BinaryFormatter(), _
                                      "{0} {1}   (binary: {0:B}) {1}   (hex: {0:H})", _
                                      ulngValue, vbCrLf))

      Dim bigIntValue As BigInteger = BigInteger.Multiply(Int64.MaxValue, 2)
      Console.WriteLine(String.Format(New BinaryFormatter(), _
                                      "{0} {1}   (binary: {0:B}) {1}   (hex: {0:H})", _
                                      bigIntValue, vbCrLf))
   End Sub
End Module
' The example displays the following output:
'    124 (binary: 01111100) (hex: 7c)
'    23045 (binary: 00000000 00000000 01011010 00000101) (hex: 00 00 5a 05)
'    31906574882
'       (binary: 00000000 00000000 00000000 00000111 01101101 11000111 10110010 00100010)
'       (hex: 00 00 00 07 6d c7 b2 22)
'    18446744073709551614
'       (binary: 00000000 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110)
'       (hex: 00 ff ff ff ff ff ff ff fe)

注解

接口包含一个方法, 即ICustomFormatter.FormatICustomFormatterThe ICustomFormatter interface includes a single method, ICustomFormatter.Format. 当通过引用或值类型实现此接口时, 该Format方法将返回对象值的自定义格式的字符串表示形式。When this interface is implemented by a reference or value type, the Format method returns a custom-formatted string representation of an object's value.

通常, ICustomFormatter接口是IFormatProvider使用接口实现的, 以自定义包含IFormatProvider参数的两 .NET Framework 复合字符串格式设置方法的行为。Typically, the ICustomFormatter interface is implemented with the IFormatProvider interface to customize the behavior of two .NET Framework composite string formatting methods that include an IFormatProvider parameter. 具体而言, ICustomFormatter接口可以提供传递String.Format(IFormatProvider, String, Object[])给和StringBuilder.AppendFormat(IFormatProvider, String, Object[])方法的对象的值的自定义格式。Specifically, the ICustomFormatter interface can provide custom formatting of the value of an object passed to the String.Format(IFormatProvider, String, Object[]) and StringBuilder.AppendFormat(IFormatProvider, String, Object[]) methods.

如果提供对象值的自定义表示形式, 则需要执行以下操作:Providing a custom representation of an object's value requires that you do the following:

  1. 定义一个实现ICustomFormatter接口及其单个成员Format (即方法) 的类。Define a class that implements the ICustomFormatter interface and its single member, the Format method.

  2. 定义一个实现IFormatProvider接口及其单个成员GetFormat (即方法) 的类。Define a class that implements the IFormatProvider interface and its single member, the GetFormat method. 方法返回ICustomFormatter实现的实例。 GetFormatThe GetFormat method returns an instance of your ICustomFormatter implementation. 通常, 单个类实现ICustomFormatter和。 IFormatProviderOften, a single class implements both ICustomFormatter and IFormatProvider. 在这种情况下, 类GetFormat的实现只返回自身的实例。In that case, the class's GetFormat implementation just returns an instance of itself.

  3. 将实现作为方法String.Format(IFormatProvider, String, Object[])的参数或类似的方法传递。provider IFormatProviderPass the IFormatProvider implementation as the provider argument of the String.Format(IFormatProvider, String, Object[]) method or a comparable method.

然后, .NET Framework 方法将使用您的自定义格式设置, 而不是自己的格式。The .NET Framework method will then use your custom formatting instead of its own.

实施者说明

公共语言运行时尝试对复合格式ICustomFormatter字符串中的每个格式项使用您的实现。The common language runtime attempts to use your ICustomFormatter implementation for every format item in a composite format string. 因此, 您应该会发现您ICustomFormatter的实现将被调用以向其设计不处理的对象或值提供格式设置服务。As a result, you should expect that your ICustomFormatter implementation will be called to provide formatting services to objects or values that it is not designed to handle. 在这些情况下, Format(String, Object, IFormatProvider)你的方法必须为该对象或值调用适当的格式设置方法。In these cases, your Format(String, Object, IFormatProvider) method must call the appropriate formatting method for that object or value.

有两种类型的ICustomFormatter实现: 内部和扩展。There are two kinds of ICustomFormatter implementations: intrinsic and extension.

内部实现是为应用程序定义的对象提供自定义格式设置的实现。Intrinsic implementations are implementations that provide custom formatting for an application-defined object. 在这种情况下, 你的实现应包含以下内容:In this case, your implementation should include the following: -定义对象格式的格式字符串的定义。- A definition of format strings that define the formatting of the object. 格式字符串是可选的。Format strings are optional. 通常, "G" 或 "g" 格式字符串定义常规 (或最常使用的) 格式。Typically, a "G" or "g" format string defines the general (or most commonly used) format. 但是, 可以随意定义所选的任何格式字符串。However, you are free to define any format strings that you choose. 您还可以随意确定它们是否区分大小写或不区分大小写。You are also free to decide whether they are case-sensitive or case-insensitive.

-一个测试, 可确保传递给Format(String, Object, IFormatProvider)方法的对象类型是应用程序定义的类型。- A test to ensure that the type of the object passed to your Format(String, Object, IFormatProvider) method is your application-defined type. 如果不是, 则应调用该对象的IFormattable实现 (如果存在) 或其ToString()方法 (如果不存在)。If it is not, you should call the object's IFormattable implementation, if one exists, or its ToString() method, if it does not. 应准备好处理这些方法调用可能会引发的任何异常。You should be prepared to handle any exceptions these method calls might throw.

-如果实现支持格式字符串, 则为处理 null 格式字符串的代码。- Code to handle a null format string, if your implementation supports format strings. 最常见的方法是将 null 格式字符串替换为常规格式说明符。The most common approach is to replace a null format string with the general format specifier.

-用于处理实现所支持的任何格式字符串的代码。- Code to handle any format strings that your implementation supports.

-用于处理不支持的格式字符串的代码。- Code to handle format strings that you do not support. 最常见的方法是引发FormatException, 尽管可以提供默认格式设置。The most common approach is to throw a FormatException, although you can provide default formatting.

扩展实现是为已具有格式设置支持的类型提供自定义格式设置的实现。Extension implementations are implementations that provide custom formatting for a type that already has formatting support. 例如, 可以定义一个CustomerNumberFormatter , 它使用特定数字之间的连字符设置整数类型的格式。For example, you could define a CustomerNumberFormatter that formats an integral type with hyphens between specific digits. 在这种情况下, 你的实现应包含以下内容:In this case, your implementation should include the following: -扩展对象格式的格式字符串的定义。- A definition of format strings that extend the formatting of the object. 这些格式字符串是必需的, 但它们不能与类型的现有格式字符串冲突。These format strings are required, but they must not conflict with the type's existing format strings. 例如, 如果要扩展Int32类型的格式, 则不应实现 "C"、"D"、"E"、"F" 和 "G" 格式说明符。For example, if you are extending formatting for the Int32 type, you should not implement the "C", "D", "E", "F", and "G" format specifiers, among others.

-一个测试, 传递给Format(String, Object, IFormatProvider)方法的对象类型是一种其扩展插件所支持的类型。- A test that the type of the object passed to your Format(String, Object, IFormatProvider) method is a type whose formatting your extension supports. 如果不是, 则调用对象的IFormattable实现 (如果存在) 或对象的无参数ToString()方法 (如果不存在)。If it is not, call the object's IFormattable implementation, if one exists, or the object's parameterless ToString() method, if it does not. 应准备好处理这些方法调用可能会引发的任何异常。You should be prepared to handle any exceptions these method calls might throw.

-用于处理扩展插件支持的任何格式字符串的代码。- Code to handle any format strings that your extension supports.

-用于处理扩展插件不支持的任何格式字符串的代码。- Code to handle any format strings that your extension does not support. 这些应传递到类型的IFormattable实现。These should be passed on to the type's IFormattable implementation. 应准备好处理这些方法调用可能会引发的任何异常。You should be prepared to handle any exceptions these method calls might throw.

方法

Format(String, Object, IFormatProvider) Format(String, Object, IFormatProvider) Format(String, Object, IFormatProvider) Format(String, Object, IFormatProvider)

使用指定的格式和区域性特定格式设置信息将指定对象的值转换为等效的字符串表示形式。Converts the value of a specified object to an equivalent string representation using specified format and culture-specific formatting information.

适用于

另请参阅