Advertisement
Guest User

Untitled

a guest
Feb 28th, 2020
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.88 KB | None | 0 0
  1. private void InitMapperDelegate(IDataRecord dataRecord)
  2. {
  3.             var columnList = _columns ?? (_columns = InitColumns(dataRecord));
  4.  
  5.             var dynMeth = new DynamicMethod("GeneratedMapperMethod", null, new Type[] { typeof(IDataRecord), typeof(TData) });
  6.             ILGenerator gen = dynMeth.GetILGenerator();
  7.            
  8.             for (int i = 0; i < columnList.Length; i++)
  9.             {
  10.                 var colName = columnList[i];
  11.                 (PropertyInfo PropInfo, DbFieldAttribute DbField) attr;
  12.                 try
  13.                 {
  14.                     attr = TableMetadata.Values.First(mtd => mtd.DbField.ColumnName == colName);
  15.                 }
  16.                 catch (Exception ex)
  17.                 {
  18.                     throw new InvalidOperationException($"Не найдено свойство объекта, соответствующее полю '{colName}'", ex);
  19.                 }
  20.  
  21.                 if (attr.DbField.DataReaderMethod == null)
  22.                     throw new InvalidOperationException($"Не найден метод чтения значения из поля '{colName}'");
  23.  
  24.                 var prop = attr.PropInfo;
  25.                 var dataType = prop.PropertyType.Name != "Nullable`1" ? prop.PropertyType : prop.PropertyType.UnderlyingSystemType.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic).FieldType;
  26.                 var valueType = dataRecord.GetFieldType(i);
  27.  
  28.                 gen.BeginExceptionBlock();
  29.  
  30.                 var endIfLabel = gen.DefineLabel();
  31.  
  32.                 gen.Emit(OpCodes.Ldarg_0); // IDataRecord
  33.                 gen.Emit(OpCodes.Ldc_I4, i);
  34.                 gen.Emit(OpCodes.Callvirt, typeof(IDataRecord).GetMethod("IsDBNull"));
  35.                 gen.Emit(OpCodes.Brtrue, endIfLabel);
  36.  
  37.                 gen.Emit(OpCodes.Ldarg_1); // TData object -- кладем заранее, возьмется при вызове сеттера
  38.                 gen.Emit(OpCodes.Isinst, typeof(TData));
  39.  
  40.                 gen.Emit(OpCodes.Ldarg_0); // IDataRecord
  41.                 gen.Emit(OpCodes.Ldc_I4, i);
  42.                 if (dataType == typeof(byte[]))
  43.                     // вызываем метод который сможет добраться до массива байт
  44.                     gen.Emit(OpCodes.Call, typeof(DataReaderExtensions).GetMethod("GetBytes", new[] { typeof(IDataRecord), typeof(int) }));
  45.                 else
  46.                     gen.Emit(OpCodes.Callvirt, typeof(IDataRecord).GetMethod("GetValue"));
  47.  
  48.                 if (prop.PropertyType.IsEnum)
  49.                     gen.Emit(OpCodes.Unbox_Any, Enum.GetUnderlyingType(prop.PropertyType));
  50.                 else if (prop.PropertyType.IsValueType || prop.PropertyType.Name == "Nullable`1")
  51.                     gen.Emit(OpCodes.Unbox_Any, valueType);
  52.                 else
  53.                     gen.Emit(OpCodes.Castclass, prop.PropertyType);
  54.  
  55.                 if (dataType != valueType && !dataType.IsEnum && dataType != typeof(byte[]))
  56.                 {
  57.                     if (dataType == typeof(decimal))
  58.                         gen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToDecimal", new[] { valueType }));
  59.                     else
  60.                         gen.Emit(GetConvertOpcode(dataType));
  61.                 }
  62.  
  63.                 gen.Emit(OpCodes.Callvirt, prop.SetMethod);
  64.                 gen.MarkLabel(endIfLabel);
  65.  
  66.                 gen.BeginCatchBlock(typeof(Exception));
  67.                 gen.Emit(OpCodes.Ldstr, $"EXCEPTION: Failed to set property {prop.Name} of type {dataType}: VALUE is {valueType}");
  68.                 gen.Emit(OpCodes.Call, typeof(Debug).GetMethod("WriteLine", new[] { typeof(string) }));
  69.                 gen.EndExceptionBlock();                
  70.             }
  71.             gen.Emit(OpCodes.Ret);
  72.             _mapDelegate = (Action<IDataRecord, TData>)dynMeth.CreateDelegate(typeof(Action<IDataRecord, TData>));
  73.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement