@@ -202,53 +202,60 @@ public override object TryConvert (EvaluationContext ctx, object obj, object tar
202
202
return null ;
203
203
}
204
204
205
+ static Dictionary < string , TypeCastDelegate > typeCastDelegatesCache = new Dictionary < string , TypeCastDelegate > ( ) ;
205
206
static TypeCastDelegate GenerateTypeCastDelegate ( string methodName , Type fromType , Type toType )
206
207
{
207
- var argTypes = new [ ] { typeof ( object ) } ;
208
- var method = new DynamicMethod ( methodName , typeof ( object ) , argTypes , true ) ;
209
- ILGenerator il = method . GetILGenerator ( ) ;
210
- ConstructorInfo ctorInfo ;
211
- MethodInfo methodInfo ;
212
- OpCode conv ;
213
-
214
- il . Emit ( OpCodes . Ldarg_0 ) ;
215
- il . Emit ( OpCodes . Unbox_Any , fromType ) ;
216
-
217
- if ( fromType . IsSubclassOf ( typeof ( Nullable ) ) ) {
218
- PropertyInfo propInfo = fromType . GetProperty ( "Value" ) ;
219
- methodInfo = propInfo . GetGetMethod ( ) ;
220
-
221
- il . Emit ( OpCodes . Stloc_0 ) ;
222
- il . Emit ( OpCodes . Ldloca_S ) ;
223
- il . Emit ( OpCodes . Call , methodInfo ) ;
224
-
225
- fromType = methodInfo . ReturnType ;
226
- }
208
+ lock ( typeCastDelegatesCache ) {
209
+ TypeCastDelegate cached ;
210
+ if ( typeCastDelegatesCache . TryGetValue ( methodName , out cached ) )
211
+ return cached ;
212
+ var argTypes = new [ ] { typeof ( object ) } ;
213
+ var method = new DynamicMethod ( methodName , typeof ( object ) , argTypes , true ) ;
214
+ ILGenerator il = method . GetILGenerator ( ) ;
215
+ ConstructorInfo ctorInfo ;
216
+ MethodInfo methodInfo ;
217
+ OpCode conv ;
218
+
219
+ il . Emit ( OpCodes . Ldarg_0 ) ;
220
+ il . Emit ( OpCodes . Unbox_Any , fromType ) ;
221
+
222
+ if ( fromType . IsSubclassOf ( typeof ( Nullable ) ) ) {
223
+ PropertyInfo propInfo = fromType . GetProperty ( "Value" ) ;
224
+ methodInfo = propInfo . GetGetMethod ( ) ;
225
+
226
+ il . Emit ( OpCodes . Stloc_0 ) ;
227
+ il . Emit ( OpCodes . Ldloca_S ) ;
228
+ il . Emit ( OpCodes . Call , methodInfo ) ;
227
229
228
- if ( ! convertOps . TryGetValue ( toType , out conv ) ) {
229
- argTypes = new [ ] { fromType } ;
230
+ fromType = methodInfo . ReturnType ;
231
+ }
230
232
231
- if ( toType == typeof ( string ) ) {
232
- methodInfo = fromType . GetMethod ( "ToString" , new Type [ 0 ] ) ;
233
- il . Emit ( OpCodes . Call , methodInfo ) ;
234
- } else if ( ( methodInfo = toType . GetMethod ( "op_Explicit" , argTypes ) ) != null ) {
235
- il . Emit ( OpCodes . Call , methodInfo ) ;
236
- } else if ( ( methodInfo = toType . GetMethod ( "op_Implicit" , argTypes ) ) != null ) {
237
- il . Emit ( OpCodes . Call , methodInfo ) ;
238
- } else if ( ( ctorInfo = toType . GetConstructor ( argTypes ) ) != null ) {
239
- il . Emit ( OpCodes . Call , ctorInfo ) ;
233
+ if ( ! convertOps . TryGetValue ( toType , out conv ) ) {
234
+ argTypes = new [ ] { fromType } ;
235
+
236
+ if ( toType == typeof ( string ) ) {
237
+ methodInfo = fromType . GetMethod ( "ToString" , new Type [ 0 ] ) ;
238
+ il . Emit ( OpCodes . Call , methodInfo ) ;
239
+ } else if ( ( methodInfo = toType . GetMethod ( "op_Explicit" , argTypes ) ) != null ) {
240
+ il . Emit ( OpCodes . Call , methodInfo ) ;
241
+ } else if ( ( methodInfo = toType . GetMethod ( "op_Implicit" , argTypes ) ) != null ) {
242
+ il . Emit ( OpCodes . Call , methodInfo ) ;
243
+ } else if ( ( ctorInfo = toType . GetConstructor ( argTypes ) ) != null ) {
244
+ il . Emit ( OpCodes . Call , ctorInfo ) ;
245
+ } else {
246
+ // No idea what else to try...
247
+ throw new InvalidCastException ( ) ;
248
+ }
240
249
} else {
241
- // No idea what else to try...
242
- throw new InvalidCastException ( ) ;
250
+ il . Emit ( conv ) ;
243
251
}
244
- } else {
245
- il . Emit ( conv ) ;
246
- }
247
252
248
- il . Emit ( OpCodes . Box , toType ) ;
249
- il . Emit ( OpCodes . Ret ) ;
250
-
251
- return ( TypeCastDelegate ) method . CreateDelegate ( typeof ( TypeCastDelegate ) ) ;
253
+ il . Emit ( OpCodes . Box , toType ) ;
254
+ il . Emit ( OpCodes . Ret ) ;
255
+ cached = ( TypeCastDelegate ) method . CreateDelegate ( typeof ( TypeCastDelegate ) ) ;
256
+ typeCastDelegatesCache [ methodName ] = cached ;
257
+ return cached ;
258
+ }
252
259
}
253
260
254
261
static object DynamicCast ( object value , Type target )
@@ -391,46 +398,7 @@ public override object TryCast (EvaluationContext ctx, object val, object type)
391
398
if ( val == null )
392
399
return null ;
393
400
394
- object res ;
395
-
396
- try {
397
- if ( tt == typeof ( bool ) )
398
- res = System . Convert . ToBoolean ( val ) ;
399
- else if ( tt == typeof ( byte ) )
400
- res = System . Convert . ToByte ( val ) ;
401
- else if ( tt == typeof ( sbyte ) )
402
- res = System . Convert . ToSByte ( val ) ;
403
- else if ( tt == typeof ( char ) )
404
- res = System . Convert . ToChar ( val ) ;
405
- else if ( tt == typeof ( short ) )
406
- res = System . Convert . ToInt16 ( val ) ;
407
- else if ( tt == typeof ( ushort ) )
408
- res = System . Convert . ToUInt16 ( val ) ;
409
- else if ( tt == typeof ( int ) )
410
- res = System . Convert . ToInt32 ( val ) ;
411
- else if ( tt == typeof ( uint ) )
412
- res = System . Convert . ToUInt32 ( val ) ;
413
- else if ( tt == typeof ( long ) )
414
- res = System . Convert . ToInt64 ( val ) ;
415
- else if ( tt == typeof ( ulong ) )
416
- res = System . Convert . ToUInt64 ( val ) ;
417
- else if ( tt == typeof ( float ) )
418
- res = System . Convert . ToSingle ( val ) ;
419
- else if ( tt == typeof ( double ) )
420
- res = System . Convert . ToDouble ( val ) ;
421
- else if ( tt == typeof ( decimal ) )
422
- res = System . Convert . ToDecimal ( val ) ;
423
- else if ( tt == typeof ( string ) )
424
- res = System . Convert . ToString ( val ) ;
425
- else if ( tt == typeof ( DateTime ) )
426
- res = System . Convert . ToDateTime ( val ) ;
427
- else
428
- res = val ;
429
- } catch {
430
- res = DynamicCast ( val , tt ) ;
431
- }
432
-
433
- return CreateValue ( ctx , res ) ;
401
+ return CreateValue ( ctx , DynamicCast ( val , tt ) ) ;
434
402
}
435
403
436
404
fromType = ( TypeMirror ) ForceLoadType ( ctx , ( ( Type ) valueType ) . FullName ) ;
0 commit comments