@@ -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 )
0 commit comments