Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- private void InitMapperDelegate(IDataRecord dataRecord)
- {
- var columnList = _columns ?? (_columns = InitColumns(dataRecord));
- var dynMeth = new DynamicMethod("GeneratedMapperMethod", null, new Type[] { typeof(IDataRecord), typeof(TData) });
- ILGenerator gen = dynMeth.GetILGenerator();
- for (int i = 0; i < columnList.Length; i++)
- {
- var colName = columnList[i];
- (PropertyInfo PropInfo, DbFieldAttribute DbField) attr;
- try
- {
- attr = TableMetadata.Values.First(mtd => mtd.DbField.ColumnName == colName);
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException($"Не найдено свойство объекта, соответствующее полю '{colName}'", ex);
- }
- if (attr.DbField.DataReaderMethod == null)
- throw new InvalidOperationException($"Не найден метод чтения значения из поля '{colName}'");
- var prop = attr.PropInfo;
- var dataType = prop.PropertyType.Name != "Nullable`1" ? prop.PropertyType : prop.PropertyType.UnderlyingSystemType.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic).FieldType;
- var valueType = dataRecord.GetFieldType(i);
- gen.BeginExceptionBlock();
- var endIfLabel = gen.DefineLabel();
- gen.Emit(OpCodes.Ldarg_0); // IDataRecord
- gen.Emit(OpCodes.Ldc_I4, i);
- gen.Emit(OpCodes.Callvirt, typeof(IDataRecord).GetMethod("IsDBNull"));
- gen.Emit(OpCodes.Brtrue, endIfLabel);
- gen.Emit(OpCodes.Ldarg_1); // TData object -- кладем заранее, возьмется при вызове сеттера
- gen.Emit(OpCodes.Isinst, typeof(TData));
- gen.Emit(OpCodes.Ldarg_0); // IDataRecord
- gen.Emit(OpCodes.Ldc_I4, i);
- if (dataType == typeof(byte[]))
- // вызываем метод который сможет добраться до массива байт
- gen.Emit(OpCodes.Call, typeof(DataReaderExtensions).GetMethod("GetBytes", new[] { typeof(IDataRecord), typeof(int) }));
- else
- gen.Emit(OpCodes.Callvirt, typeof(IDataRecord).GetMethod("GetValue"));
- if (prop.PropertyType.IsEnum)
- gen.Emit(OpCodes.Unbox_Any, Enum.GetUnderlyingType(prop.PropertyType));
- else if (prop.PropertyType.IsValueType || prop.PropertyType.Name == "Nullable`1")
- gen.Emit(OpCodes.Unbox_Any, valueType);
- else
- gen.Emit(OpCodes.Castclass, prop.PropertyType);
- if (dataType != valueType && !dataType.IsEnum && dataType != typeof(byte[]))
- {
- if (dataType == typeof(decimal))
- gen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToDecimal", new[] { valueType }));
- else
- gen.Emit(GetConvertOpcode(dataType));
- }
- gen.Emit(OpCodes.Callvirt, prop.SetMethod);
- gen.MarkLabel(endIfLabel);
- gen.BeginCatchBlock(typeof(Exception));
- gen.Emit(OpCodes.Ldstr, $"EXCEPTION: Failed to set property {prop.Name} of type {dataType}: VALUE is {valueType}");
- gen.Emit(OpCodes.Call, typeof(Debug).GetMethod("WriteLine", new[] { typeof(string) }));
- gen.EndExceptionBlock();
- }
- gen.Emit(OpCodes.Ret);
- _mapDelegate = (Action<IDataRecord, TData>)dynMeth.CreateDelegate(typeof(Action<IDataRecord, TData>));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement