1
1
using Kros . Caching ;
2
+ using Kros . Extensions ;
2
3
using Kros . KORM . Converter ;
3
4
using Kros . KORM . Injection ;
4
5
using Kros . KORM . Metadata ;
@@ -27,7 +28,6 @@ public class DynamicMethodModelFactory : IModelFactory
27
28
private readonly static List < IConverter > _converters = new List < IConverter > ( ) ;
28
29
private readonly static List < IInjector > _injectors = new List < IInjector > ( ) ;
29
30
30
- private readonly static ICache < string , MethodInfo > _methodsInfo = new Cache < string , MethodInfo > ( ) ;
31
31
private readonly static MethodInfo _fnIsDBNull = typeof ( IDataRecord ) . GetMethod ( "IsDBNull" ) ;
32
32
private readonly static MethodInfo _fnGetValue = typeof ( IDataRecord ) . GetMethod ( "GetValue" , new Type [ ] { typeof ( int ) } ) ;
33
33
private readonly static MethodInfo _fnConvert = typeof ( IConverter ) . GetMethod ( "Convert" ) ;
@@ -39,6 +39,9 @@ public class DynamicMethodModelFactory : IModelFactory
39
39
private readonly static MethodInfo _fnInjectorsListGetItem = typeof ( List < IInjector > ) . GetProperty ( "Item" ) . GetGetMethod ( ) ;
40
40
private readonly static MethodInfo _fnInjectorMethodInfo =
41
41
typeof ( IInjector ) . GetMethod ( nameof ( IInjector . GetValue ) , new Type [ ] { typeof ( string ) } ) ;
42
+ private readonly static Dictionary < string , MethodInfo > _readerValueGetters = InitReaderValueGetters ( ) ;
43
+ private readonly static MethodInfo _getValueMethodInfo =
44
+ typeof ( IDataRecord ) . GetMethod ( "GetValue" , new Type [ ] { typeof ( int ) } ) ;
42
45
43
46
#endregion
44
47
@@ -51,9 +54,7 @@ public class DynamicMethodModelFactory : IModelFactory
51
54
/// <exception cref="System.ArgumentNullException">databaseMapper;Argument 'databaseMapper' is required.</exception>
52
55
public DynamicMethodModelFactory ( IDatabaseMapper databaseMapper )
53
56
{
54
- Check . NotNull ( databaseMapper , nameof ( databaseMapper ) ) ;
55
-
56
- _databaseMapper = databaseMapper ;
57
+ _databaseMapper = Check . NotNull ( databaseMapper , nameof ( databaseMapper ) ) ;
57
58
}
58
59
59
60
#endregion
@@ -111,8 +112,7 @@ private static T FactoryForValueType<T>(IDataReader reader)
111
112
Type destType = typeof ( T ) ;
112
113
Type srcType = reader . GetFieldType ( 0 ) ;
113
114
114
- var valueGetter = _methodsInfo . Get ( srcType . Name ,
115
- ( ) => typeof ( IDataRecord ) . GetMethod ( "Get" + srcType . Name , new Type [ ] { typeof ( int ) } ) ) ;
115
+ var valueGetter = GetReaderValueGetter ( srcType ) ;
116
116
117
117
var value = valueGetter . Invoke ( reader , new object [ ] { 0 } ) ;
118
118
if ( destType . Name == srcType . Name )
@@ -261,10 +261,9 @@ private static void FillingValuesWithoutConverter(ILGenerator ilGenerator,
261
261
ColumnInfo columnInfo ,
262
262
Type srcType )
263
263
{
264
- bool ? castNeeded = null ;
264
+ bool castNeeded = false ;
265
265
266
- var valuegetter = _methodsInfo . Get ( srcType . Name ,
267
- ( ) => typeof ( IDataRecord ) . GetMethod ( "Get" + srcType . Name , new Type [ ] { typeof ( int ) } ) ) ;
266
+ MethodInfo valuegetter = GetReaderValueGetter ( srcType ) ;
268
267
269
268
if ( valuegetter != null
270
269
&& valuegetter . ReturnType == srcType
@@ -273,37 +272,80 @@ private static void FillingValuesWithoutConverter(ILGenerator ilGenerator,
273
272
{
274
273
castNeeded = false ;
275
274
}
275
+ else if ( ( srcType == columnInfo . PropertyInfo . PropertyType ) ||
276
+ ( srcType == Nullable . GetUnderlyingType ( columnInfo . PropertyInfo . PropertyType ) ) )
277
+ {
278
+ valuegetter = _getValueMethodInfo ;
279
+ castNeeded = true ;
280
+ }
276
281
else
277
282
{
278
- if ( srcType == typeof ( byte [ ] ) && srcType == columnInfo . PropertyInfo . PropertyType )
279
- {
280
- valuegetter = typeof ( IDataRecord ) . GetMethod ( "GetValue" , new Type [ ] { typeof ( int ) } ) ;
281
- castNeeded = true ;
282
- }
283
+ throw new InvalidOperationException (
284
+ Properties . Resources . CannotMaterializeSourceValue . Format ( srcType , columnInfo . PropertyInfo . PropertyType ) ) ;
283
285
}
284
286
285
- if ( castNeeded . HasValue )
286
- {
287
- ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
288
- ilGenerator . Emit ( OpCodes . Ldc_I4 , fieldIndex ) ;
289
- ilGenerator . Emit ( OpCodes . Callvirt , valuegetter ) ;
287
+ ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
288
+ ilGenerator . Emit ( OpCodes . Ldc_I4 , fieldIndex ) ;
289
+ ilGenerator . Emit ( OpCodes . Callvirt , valuegetter ) ;
290
290
291
- if ( castNeeded . Value )
292
- {
293
- ilGenerator . Emit ( OpCodes . Castclass , columnInfo . PropertyInfo . PropertyType ) ;
294
- }
295
- else
291
+ if ( castNeeded )
292
+ {
293
+ EmitCastValue ( ilGenerator , columnInfo , srcType ) ;
294
+ }
295
+ else
296
+ {
297
+ if ( Nullable . GetUnderlyingType ( columnInfo . PropertyInfo . PropertyType ) != null )
296
298
{
297
- if ( Nullable . GetUnderlyingType ( columnInfo . PropertyInfo . PropertyType ) != null )
298
- {
299
- ilGenerator . Emit ( OpCodes . Newobj ,
300
- columnInfo . PropertyInfo . PropertyType . GetConstructor (
301
- new Type [ ] { Nullable . GetUnderlyingType ( columnInfo . PropertyInfo . PropertyType ) } ) ) ;
302
- }
299
+ ilGenerator . Emit ( OpCodes . Newobj ,
300
+ columnInfo . PropertyInfo . PropertyType . GetConstructor (
301
+ new Type [ ] { Nullable . GetUnderlyingType ( columnInfo . PropertyInfo . PropertyType ) } ) ) ;
303
302
}
303
+ }
304
304
305
- ilGenerator . Emit ( OpCodes . Callvirt , columnInfo . PropertyInfo . GetSetMethod ( true ) ) ;
305
+ ilGenerator . Emit ( OpCodes . Callvirt , columnInfo . PropertyInfo . GetSetMethod ( true ) ) ;
306
+ }
307
+
308
+ private static void EmitCastValue ( ILGenerator ilGenerator , ColumnInfo columnInfo , Type srcType )
309
+ {
310
+ if ( srcType . IsValueType )
311
+ {
312
+ ilGenerator . Emit ( OpCodes . Unbox_Any , columnInfo . PropertyInfo . PropertyType ) ;
313
+ }
314
+ else
315
+ {
316
+ ilGenerator . Emit ( OpCodes . Castclass , columnInfo . PropertyInfo . PropertyType ) ;
306
317
}
307
318
}
319
+
320
+ private static Dictionary < string , MethodInfo > InitReaderValueGetters ( )
321
+ {
322
+ var getters = new Dictionary < string , MethodInfo > ( StringComparer . CurrentCultureIgnoreCase ) ;
323
+
324
+ MethodInfo CreateReaderValueGetter ( string typeName )
325
+ => typeof ( IDataRecord ) . GetMethod ( $ "Get{ typeName } ", new Type [ ] { typeof ( int ) } ) ;
326
+
327
+ void Add < T > ( )
328
+ => getters . Add ( typeof ( T ) . Name , CreateReaderValueGetter ( typeof ( T ) . Name ) ) ;
329
+
330
+ Add < Boolean > ( ) ;
331
+ Add < Byte > ( ) ;
332
+ Add < Char > ( ) ;
333
+ Add < DateTime > ( ) ;
334
+ Add < Decimal > ( ) ;
335
+ Add < Double > ( ) ;
336
+ Add < Guid > ( ) ;
337
+ Add < Int16 > ( ) ;
338
+ Add < Int32 > ( ) ;
339
+ Add < Int64 > ( ) ;
340
+
341
+ Add < String > ( ) ;
342
+
343
+ getters . Add ( nameof ( Single ) , CreateReaderValueGetter ( "Float" ) ) ;
344
+
345
+ return getters ;
346
+ }
347
+
348
+ private static MethodInfo GetReaderValueGetter ( Type srcType )
349
+ => _readerValueGetters . ContainsKey ( srcType . Name ) ? _readerValueGetters [ srcType . Name ] : null ;
308
350
}
309
351
}
0 commit comments