1 // Sample for the IFormatProvider interface and
2 // the IFormatProvider.GetFormat( Type ) method.
3 using System;
4
5 // This class implements the "Ra" formatting code. An instance of this
6 // class should be passed to methods requiring an IFormatProvider.
7 public class AnyRadix : ICustomFormatter, IFormatProvider
8 {
9 // The value to be formatted is returned as a signed string
10 // of digits from the rDigits array.
11 const string radixCode = "Ra";
12 private static char[] rDigits = {
13 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
14 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
15 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
16 'U', 'V', 'W', 'X', 'Y', 'Z' };
17
18 // This method returns an object that implements ICustomFormatter
19 // to do the formatting.
20 public object GetFormat( Type argType )
21 {
22 // Here, the same object (this) is returned, but it would
23 // be possible to return an object of a different type.
24 if ( argType == typeof( ICustomFormatter ) )
25 return this;
26 else
27 return null;
28 }
29
30 // This method does the formatting only if it recognizes the
31 // format codes.
32 public string Format( string formatString,
33 object argToBeFormatted, IFormatProvider provider )
34 {
35 // If no format string is provided or the format string cannot
36 // be handled, use IFormattable or standard string processing.
37 if( formatString == null ||
38 ! formatString.Trim( ).StartsWith( radixCode ) )
39 {
40 if( argToBeFormatted is IFormattable )//按照系统默认格式
41 return ( (IFormattable)argToBeFormatted ).ToString( formatString, provider );
42 else
43 return argToBeFormatted.ToString( );
44 }
45
46 // The formatting is handled here.
47 int digitIndex = 0;
48 long radix;
49 long longToBeFormatted;
50 long longPositive;
51 char[ ] outDigits = new char[ 63 ];
52
53 // Extract the radix from the format string.
54 formatString = formatString.Replace( radixCode, "" );
55 try
56 {
57 radix = Convert.ToInt64( formatString );
58 }
59 catch( Exception ex )
60 {
61 throw new ArgumentException( String.Format(
62 "The radix \"{0}\" is invalid.",
63 formatString ), ex );
64 }
65
66 // Verify that the radix is in the proper range.
67 if( radix <2 || radix > 36 )
68 throw new ArgumentException( String.Format(
69 "The radix \"{0}\" is not in the range 2..36.",
70 formatString ) );
71
72 // Verify that the argument can be converted to a long integer.
73 try
74 {
75 longToBeFormatted = (long)argToBeFormatted;
76 }
77 catch( Exception ex )
78 {
79 throw new ArgumentException( String.Format(
80 "The argument \"{0}\" cannot be " +
81 "converted to an integer value.",
82 argToBeFormatted ), ex );
83 }
84
85 // Extract the magnitude for conversion.
86 longPositive = Math.Abs( longToBeFormatted );
87
88 // Convert the magnitude to a digit string.
89 for( digitIndex = 0; digitIndex <= 64; digitIndex++ )
90 {
91 if( longPositive == 0 ) break;
92
93 outDigits[ outDigits.Length - digitIndex - 1 ] =
94 rDigits[ longPositive % radix ];
95 longPositive /= radix;
96 }
97
98 // Add a minus sign if the argument is negative.
99 if( longToBeFormatted < 0 )
100 outDigits[ outDigits.Length - digitIndex++ - 1 ] =
101 '-';
102
103 return new string( outDigits,
104 outDigits.Length - digitIndex, digitIndex );
105 }
106 }
107
108 class IFormatProviderDemo
109 {
110 static void ConvertToAnyRadix( object argToConvert,
111 string formatStr )
112 {
113 AnyRadix provider = new AnyRadix( );
114 string messageStr =
115 String.Format( "{{0:{0}}}", formatStr );
116
117 // Write the first part of the output line.
118 Console.Write( "{0,18} {1,-6}", argToConvert, formatStr );
119
120 // Convert the specified argument using the specified format.
121 try
122 {
123 Console.WriteLine( String.Format(
124 provider, messageStr, argToConvert ) );
125 }
126 catch( Exception ex )
127 {
128 // Display the exception without the stack trace.
129 int lineEnd = ex.ToString( ).IndexOf( '\n' );
130 Console.WriteLine( "{0}\n",
131 ex.ToString( ).Substring( 0, lineEnd ) );
132 }
133 }
134
135 static void Main( )
136 {
137 long twoToThe32 = 4294967296;
138 long fifteenNines = 999999999999999;
139
140 Console.WriteLine(
141 "This example of the IFormatProvider interface \n" +
142 "and the IFormatProvider.GetFormat( Type ) method " +
143 "\ngenerates the following output.\n" );
144 Console.WriteLine( "{0,18} Format Result", "Number" );
145 Console.WriteLine( "{0,18} ------ ------", "------" );
146
147 // These are valid conversions.
148 ConvertToAnyRadix( twoToThe32, "Ra2" );
149 ConvertToAnyRadix( twoToThe32, "Ra5" );
150 ConvertToAnyRadix( twoToThe32, "Ra16" );
151 ConvertToAnyRadix( twoToThe32, "Ra23" );
152 ConvertToAnyRadix( twoToThe32, "Ra36" );
153 ConvertToAnyRadix( fifteenNines, "Ra2" );
154 ConvertToAnyRadix( fifteenNines, "Ra3" );
155 ConvertToAnyRadix( fifteenNines, "Ra8" );
156 ConvertToAnyRadix( fifteenNines, "Ra11" );
157 ConvertToAnyRadix( fifteenNines, "Ra16" );
158 ConvertToAnyRadix( fifteenNines, "Ra23" );
159 ConvertToAnyRadix( fifteenNines, "Ra36" );
160 ConvertToAnyRadix( fifteenNines, "E16" );
161 ConvertToAnyRadix( fifteenNines, "" );
162
163 // These are error conditions.
164 ConvertToAnyRadix( fifteenNines, "Ra37" );
165 ConvertToAnyRadix( "ABCDEFGHIJKLM", "Ra16" );
166 }
167 }
168
169 /*
170 This example of the IFormatProvider interface
171 and the IFormatProvider.GetFormat( Type ) method
172 generates the following output.
173
174 Number Format Result
175 ------ ------ ------
176 4294967296 Ra2 100000000000000000000000000000000
177 4294967296 Ra5 32244002423141
178 4294967296 Ra16 100000000
179 4294967296 Ra23 1606K7IC
180 4294967296 Ra36 1Z141Z4
181 999999999999999 Ra2 11100011010111111010100100110001100111111111111111
182 999999999999999 Ra3 11212010201001210101011021212000
183 999999999999999 Ra8 34327724461477777
184 999999999999999 Ra11 26A6A3689065639
185 999999999999999 Ra16 38D7EA4C67FFF
186 999999999999999 Ra23 1134DIFHLMM4
187 999999999999999 Ra36 9UGXNORJLR
188 999999999999999 E16 9.9999999999999900E+014
189 999999999999999 999999999999999
190 999999999999999 Ra37 System.ArgumentException: The radix "37" is not in th
191 e range 2..36.
192
193 ABCDEFGHIJKLM Ra16 System.ArgumentException: The argument "ABCDEFGHIJKLM
194 " cannot be converted to an integer value. ---> System.InvalidCastException: Sp
195 ecified cast is not valid.
196 */