/// <summary> /// Returns attribute information based on field information /// </summary> public MemberInfo FindMember(MemberInfo[] properties, DataReaderCellInfo dataInfo) { foreach (var item in properties) { if (item.Name.Equals(dataInfo.DataName, StringComparison.OrdinalIgnoreCase)) { return(item); } else if (item.Name.Equals(dataInfo.DataName.Replace("_", ""), StringComparison.OrdinalIgnoreCase)) { return(item); } } return(null); }
/// <summary> /// 创建动态方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="mapper"></param> /// <param name="record"></param> /// <returns></returns> private Func <IDataRecord, T> CreateTypeSerializerHandler <T>(MemberMapper mapper, IDataRecord record) { var type = typeof(T); var methodName = $"Serializer{Guid.NewGuid():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 DataReaderCellInfo[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 DataReaderCellInfo(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); } if (type == typeof(object) && convertMethod.ReturnType.IsValueType) { generator.Emit(OpCodes.Box, convertMethod.ReturnType); } 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>); } }