/// <summary> /// Returns attribute information based on field information /// </summary> public MemberInfo FindMember(MemberInfo[] properties, DbDataInfo dataInfo) { foreach (var item in properties) { if (item.Name.Equals(dataInfo.DataName, StringComparison.OrdinalIgnoreCase)) { return(item); } else if (//SqlMapper.MatchNamesWithUnderscores && item.Name.Equals(dataInfo.DataName.Replace("_", ""), StringComparison.OrdinalIgnoreCase)) { return(item); } } return(null); }
private static Func <IDataRecord, T> CreateTypeSerializerHandler <T>(ITypeMapper mapper, IDataRecord record) { var type = typeof(T); var methodName = $"{type.Name}Serializer{Guid.NewGuid().ToString("N")}"; var dynamicMethod = new DynamicMethod(methodName, type, new Type[] { typeof(IDataRecord) }, type, true); var generator = dynamicMethod.GetILGenerator(); LocalBuilder local = generator.DeclareLocal(type); var dataInfos = new DbDataInfo[record.FieldCount]; for (int i = 0; i < record.FieldCount; i++) { var dataname = record.GetName(i); var datatype = record.GetFieldType(i); var typename = record.GetDataTypeName(i); dataInfos[i] = new DbDataInfo(i, typename, datatype, dataname); } if (dataInfos.Length == 1 && (type.IsValueType || type == typeof(string) || type == typeof(object))) { var dataInfo = dataInfos.First(); var convertMethod = mapper.FindConvertMethod(type, dataInfo.DataType); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, 0); if (convertMethod.IsVirtual) { generator.Emit(OpCodes.Callvirt, convertMethod); } else { generator.Emit(OpCodes.Call, convertMethod); } generator.Emit(OpCodes.Stloc, local); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); return(dynamicMethod.CreateDelegate(typeof(Func <IDataRecord, T>)) as Func <IDataRecord, T>); } var constructor = mapper.FindConstructor(type); if (constructor.GetParameters().Length > 0) { var parameters = constructor.GetParameters(); var locals = new LocalBuilder[parameters.Length]; for (int i = 0; i < locals.Length; i++) { locals[i] = generator.DeclareLocal(parameters[i].ParameterType); } for (int i = 0; i < locals.Length; i++) { var item = mapper.FindConstructorParameter(dataInfos, parameters[i]); if (item == null) { continue; } var convertMethod = mapper.FindConvertMethod(parameters[i].ParameterType, item.DataType); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, item.Ordinal); if (convertMethod.IsVirtual) { generator.Emit(OpCodes.Callvirt, convertMethod); } else { generator.Emit(OpCodes.Call, convertMethod); } generator.Emit(OpCodes.Stloc, locals[i]); } for (int i = 0; i < locals.Length; i++) { generator.Emit(OpCodes.Ldloc, locals[i]); } generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Stloc, local); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); return(dynamicMethod.CreateDelegate(typeof(Func <IDataRecord, T>)) as Func <IDataRecord, T>); } else { var properties = type.GetProperties(); generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Stloc, local); foreach (var item in dataInfos) { var property = mapper.FindMember(properties, item) as PropertyInfo; if (property == null) { continue; } var convertMethod = mapper.FindConvertMethod(property.PropertyType, item.DataType); if (convertMethod == null) { continue; } int i = record.GetOrdinal(item.DataName); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); if (convertMethod.IsVirtual) { generator.Emit(OpCodes.Callvirt, convertMethod); } else { generator.Emit(OpCodes.Call, convertMethod); } generator.Emit(OpCodes.Callvirt, property.GetSetMethod()); } generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); return(dynamicMethod.CreateDelegate(typeof(Func <IDataRecord, T>)) as Func <IDataRecord, T>); } }