3
3
4
4
using System ;
5
5
using System . Collections ;
6
+ using System . ComponentModel ;
6
7
using System . Globalization ;
7
8
using System . Reflection ;
8
9
@@ -53,7 +54,7 @@ public virtual object ConvertTo([NotNull] Type type, CultureInfo culture)
53
54
if ( value == null )
54
55
{
55
56
// treat null route parameters as though they were the default value for the type
56
- return type . GetTypeInfo ( ) . IsValueType ? Activator . CreateInstance ( type ) :
57
+ return type . GetTypeInfo ( ) . IsValueType ? Activator . CreateInstance ( type ) :
57
58
null ;
58
59
}
59
60
@@ -68,7 +69,7 @@ public virtual object ConvertTo([NotNull] Type type, CultureInfo culture)
68
69
69
70
public static bool CanConvertFromString ( Type destinationType )
70
71
{
71
- return GetConverterDelegate ( destinationType ) != null ;
72
+ return GetConverterDelegate ( typeof ( string ) , destinationType ) != null ;
72
73
}
73
74
74
75
private object ConvertSimpleType ( CultureInfo culture , object value , Type destinationType )
@@ -88,7 +89,7 @@ private object ConvertSimpleType(CultureInfo culture, object value, Type destina
88
89
return null ;
89
90
}
90
91
91
- var converter = GetConverterDelegate ( destinationType ) ;
92
+ var converter = GetConverterDelegate ( value . GetType ( ) , destinationType ) ;
92
93
if ( converter == null )
93
94
{
94
95
var message = Resources . FormatValueProviderResult_NoConverterExists ( value . GetType ( ) , destinationType ) ;
@@ -144,121 +145,58 @@ private object UnwrapPossibleArrayType(CultureInfo culture, object value, Type d
144
145
return ConvertSimpleType ( culture , value , destinationType ) ;
145
146
}
146
147
147
- private static Func < object , CultureInfo , object > GetConverterDelegate ( Type destinationType )
148
+ private static Func < object , CultureInfo , object > GetConverterDelegate ( Type sourceType , Type destinationType )
148
149
{
149
150
destinationType = UnwrapNullableType ( destinationType ) ;
150
-
151
- if ( destinationType == typeof ( string ) )
152
- {
153
- return ( value , culture ) => Convert . ToString ( value , culture ) ;
154
- }
155
-
156
- if ( destinationType == typeof ( int ) )
157
- {
158
- return ( value , culture ) => Convert . ToInt32 ( value , culture ) ;
159
- }
160
-
161
- if ( destinationType == typeof ( long ) )
162
- {
163
- return ( value , culture ) => Convert . ToInt64 ( value , culture ) ;
164
- }
165
-
166
- if ( destinationType == typeof ( float ) )
167
- {
168
- return ( value , culture ) => Convert . ToSingle ( value , culture ) ;
169
- }
170
-
171
- if ( destinationType == typeof ( double ) )
151
+ var converter = TypeDescriptor . GetConverter ( destinationType ) ;
152
+ var canConvertFrom = converter . CanConvertFrom ( sourceType ) ;
153
+ if ( ! canConvertFrom )
172
154
{
173
- return ( value , culture ) => Convert . ToDouble ( value , culture ) ;
155
+ converter = TypeDescriptor . GetConverter ( sourceType ) ;
174
156
}
175
-
176
- if ( destinationType == typeof ( decimal ) )
177
- {
178
- return ( value , culture ) => Convert . ToDecimal ( value , culture ) ;
179
- }
180
-
181
- if ( destinationType == typeof ( bool ) )
182
- {
183
- return ( value , culture ) => Convert . ToBoolean ( value , culture ) ;
184
- }
185
-
186
- if ( destinationType == typeof ( DateTime ) )
157
+ if ( ! ( canConvertFrom || converter . CanConvertTo ( destinationType ) ) )
187
158
{
188
- return ( value , culture ) =>
159
+ if ( destinationType . IsEnum ( ) )
189
160
{
190
- ThrowIfNotStringType ( value , destinationType ) ;
191
- return DateTime . Parse ( ( string ) value , culture ) ;
192
- } ;
193
- }
161
+ return ( value , culture ) =>
162
+ {
163
+ // EnumConverter cannot convert integer, so we verify manually
164
+ if ( ( value is int ) )
165
+ {
166
+ if ( Enum . IsDefined ( destinationType , value ) )
167
+ {
168
+ return Enum . ToObject ( destinationType , ( int ) value ) ;
169
+ }
194
170
195
- if ( destinationType == typeof ( DateTimeOffset ) )
196
- {
197
- return ( value , culture ) =>
198
- {
199
- ThrowIfNotStringType ( value , destinationType ) ;
200
- return DateTimeOffset . Parse ( ( string ) value , culture ) ;
201
- } ;
202
- }
171
+ throw new FormatException (
172
+ Resources . FormatValueProviderResult_CannotConvertEnum ( value , destinationType ) ) ;
173
+ }
203
174
204
- if ( destinationType == typeof ( TimeSpan ) )
205
- {
206
- return ( value , culture ) =>
207
- {
208
- ThrowIfNotStringType ( value , destinationType ) ;
209
- return TimeSpan . Parse ( ( string ) value , culture ) ;
210
- } ;
211
- }
175
+ throw new InvalidOperationException (
176
+ Resources . FormatValueProviderResult_NoConverterExists ( sourceType , destinationType ) ) ;
177
+ } ;
178
+ }
212
179
213
- if ( destinationType == typeof ( Guid ) )
214
- {
215
- return ( value , culture ) =>
216
- {
217
- ThrowIfNotStringType ( value , destinationType ) ;
218
- return Guid . Parse ( ( string ) value ) ;
219
- } ;
180
+ return null ;
220
181
}
221
182
222
- if ( destinationType . GetTypeInfo ( ) . IsEnum )
183
+ return ( value , culture ) =>
223
184
{
224
- return ( value , culture ) =>
185
+ try
225
186
{
226
- // EnumConverter cannot convert integer, so we verify manually
227
- if ( ( value is int ) )
228
- {
229
- if ( Enum . IsDefined ( destinationType , value ) )
230
- {
231
- return Enum . ToObject ( destinationType , ( int ) value ) ;
232
- }
233
-
234
- throw new FormatException (
235
- Resources . FormatValueProviderResult_CannotConvertEnum ( value ,
236
- destinationType ) ) ;
237
- }
238
- else
239
- {
240
- ThrowIfNotStringType ( value , destinationType ) ;
241
- return Enum . Parse ( destinationType , ( string ) value ) ;
242
- }
243
- } ;
244
- }
245
-
246
- return null ;
187
+ return canConvertFrom ? converter . ConvertFrom ( null , culture , value ) : converter . ConvertTo ( null , culture , value , destinationType ) ;
188
+ }
189
+ catch ( Exception ex )
190
+ {
191
+ throw new InvalidOperationException (
192
+ Resources . FormatValueProviderResult_ConversionThrew ( sourceType , destinationType ) , ex ) ;
193
+ }
194
+ } ;
247
195
}
248
196
249
197
private static Type UnwrapNullableType ( Type destinationType )
250
198
{
251
199
return Nullable . GetUnderlyingType ( destinationType ) ?? destinationType ;
252
200
}
253
-
254
- private static void ThrowIfNotStringType ( object value , Type destinationType )
255
- {
256
- var type = value . GetType ( ) ;
257
- if ( type != typeof ( string ) )
258
- {
259
- var message = Resources . FormatValueProviderResult_NoConverterExists ( type , destinationType ) ;
260
- throw new InvalidOperationException ( message ) ;
261
- }
262
- }
263
201
}
264
202
}
0 commit comments