private static CreateCollectionFromDataReaderDelegate GenerateCollectionFromDataReader() { dynamicMethodCreateCollectionFromDataReader = new DynamicMethod("CreateCollectionFromDataReader", typeof(void), new Type[] { typeof(ICollection<T>), typeof(IDataReader), typeof(int[]) }, typeof(T)); ILGenerator ILout = dynamicMethodCreateCollectionFromDataReader.GetILGenerator(); MethodInfo DataReaderRead = typeof(IDataReader).GetMethod("Read"); MethodInfo CollectionAdd = typeof(ICollection<T>).GetMethod("Add"); ConstructorInfo TConstructor = typeof(T).GetConstructor(new Type[0]); LocalBuilder objectToMap = ILout.DeclareLocal(typeof(T)); LocalBuilder memberIndex = null; // Mark the datareader.read() with a label for looping Label LoopLabel = ILout.DefineLabel(); Label EndLabel = ILout.DefineLabel(); ILout.MarkLabel(LoopLabel); // calling IDataReader.Read(), if false go to EndLabel ILout.Emit(OpCodes.Ldarg_1); ILout.Emit(OpCodes.Callvirt, DataReaderRead); ILout.Emit(OpCodes.Brfalse, EndLabel); // constructing the objet ILout.Emit(OpCodes.Newobj, TConstructor); ILout.Emit(OpCodes.Stloc, objectToMap); for (int index = 0; index < classEntryToMapArray.Length; ++index) { MappedMember member = classEntryToMapArray[index]; // Push the objet from the local to the stack member.GenerateIL(ILout, index, objectToMap, ref memberIndex); } // pushing the list on the stack ILout.Emit(OpCodes.Ldarg_0); // adding the object on the map; ILout.Emit(OpCodes.Ldloc, objectToMap); ILout.Emit(OpCodes.Callvirt, CollectionAdd); // go back to IDataReader.Read() ILout.Emit(OpCodes.Br, LoopLabel); // the end of the function ILout.MarkLabel(EndLabel); ILout.Emit(OpCodes.Ret); return (CreateCollectionFromDataReaderDelegate)dynamicMethodCreateCollectionFromDataReader.CreateDelegate( typeof(CreateCollectionFromDataReaderDelegate)); }
private void GenerateILForMember(ILGenerator ILout, int index, LocalBuilder objectToMap, LocalBuilder fieldIndex) { // pushing the object to fill on the stack ILout.Emit(OpCodes.Ldloc, objectToMap); // pushing the datareader on the stack ILout.Emit(OpCodes.Ldarg_1); // Getting the ordinal value for the method/field ILout.Emit(OpCodes.Ldarg_2); ILout.Emit(OpCodes.Ldc_I4, index); ILout.Emit(OpCodes.Ldelem_I); GenerateILToGetDataFromDataReader(ILout, index, entryValueType); GenerateILToStoreDataInMember(ILout); }
private void GenerateILForMemberWithIgnoringNullValue( ILGenerator ILout, int index, LocalBuilder objectToMap, ref LocalBuilder memberIndex) { MethodInfo DataReaderIsDBNull = typeof(IDataRecord).GetMethod("IsDBNull"); if (memberIndex == null) { memberIndex = ILout.DeclareLocal(typeof(int)); } Label IgnoreNullLabel = ILout.DefineLabel(); // pushing the datareader on the stack ILout.Emit(OpCodes.Ldarg_1); //Retrieving the field index ILout.Emit(OpCodes.Ldarg_2); ILout.Emit(OpCodes.Ldc_I4, index); ILout.Emit(OpCodes.Ldelem_I); //Storing it in the fieldIndex local variable ILout.Emit(OpCodes.Dup); ILout.Emit(OpCodes.Stloc, memberIndex); // Is NULL? ILout.Emit(OpCodes.Callvirt, DataReaderIsDBNull); // If yes go to IgnoreNullLabel ILout.Emit(OpCodes.Brtrue, IgnoreNullLabel); // pushing the object to fill on the stack ILout.Emit(OpCodes.Ldloc, objectToMap); // pushing the datareader on the stack ILout.Emit(OpCodes.Ldarg_1); // Getting the ordinal value for the method/field ILout.Emit(OpCodes.Ldloc, memberIndex); GenerateILToGetDataFromDataReader(ILout, index, entryValueType); GenerateILToStoreDataInMember(ILout); ILout.MarkLabel(IgnoreNullLabel); }
private void GenerateILForNullableMember( ILGenerator ILout, int index, LocalBuilder objectToMap, ref LocalBuilder memberIndex, Type nullableType) { MethodInfo DataReaderIsDBNull = typeof(IDataRecord).GetMethod("IsDBNull"); ConstructorInfo NullableConstructor = entryValueType.GetConstructor(new Type[] { nullableType }); LocalBuilder nullLocal = ILout.DeclareLocal(entryValueType); if (memberIndex == null) { memberIndex = ILout.DeclareLocal(typeof(int)); } Label BeginIsNullBlockLabel = ILout.DefineLabel(); Label EndIsNullBlockLabel = ILout.DefineLabel(); #region Is Null? // pushing the datareader on the stack ILout.Emit(OpCodes.Ldarg_1); //Retrieving the field index ILout.Emit(OpCodes.Ldarg_2); ILout.Emit(OpCodes.Ldc_I4, index); ILout.Emit(OpCodes.Ldelem_I); //Storing it in the fieldIndex local variable ILout.Emit(OpCodes.Dup); ILout.Emit(OpCodes.Stloc, memberIndex); // Is NULL? ILout.Emit(OpCodes.Callvirt, DataReaderIsDBNull); #endregion // If yes go to BeginIsNullBlockLabel ILout.Emit(OpCodes.Brtrue, BeginIsNullBlockLabel); #region Is Not Null // pushing the object to fill on the stack ILout.Emit(OpCodes.Ldloc, objectToMap); // pushing the datareader on the stack ILout.Emit(OpCodes.Ldarg_1); // Getting the ordinal value for the method/field ILout.Emit(OpCodes.Ldloc, memberIndex); GenerateILToGetDataFromDataReader(ILout, index, nullableType); ILout.Emit(OpCodes.Newobj, NullableConstructor); // To branch after the null instruction block ILout.Emit(OpCodes.Br, EndIsNullBlockLabel); #endregion #region Is Null ILout.MarkLabel(BeginIsNullBlockLabel); // pushing the object to fill on the stack ILout.Emit(OpCodes.Ldloc, objectToMap); ILout.Emit(OpCodes.Ldloca, nullLocal.LocalIndex); // Instantiate a Nullable<T> with no value ILout.Emit(OpCodes.Initobj, entryValueType); ILout.Emit(OpCodes.Ldloc, nullLocal); #endregion ILout.MarkLabel(EndIsNullBlockLabel); GenerateILToStoreDataInMember(ILout); }
private void GenerateILToGetDataFromDataReader(ILGenerator ILout, int index, Type memberType) { MethodInfo methodInfo = Tools.getDataReaderMethod(memberType); if (methodInfo == null) { throw new Exception("Type not handled: " + classEntryToMapArray[index].EntryValueType.FullName); } ILout.Emit(OpCodes.Callvirt, methodInfo); }
private void GenerateILToStoreDataInMember(ILGenerator ILout) { switch (entryType) { case MappedMemberType.field: ILout.Emit(OpCodes.Stfld, fieldInfo); break; case MappedMemberType.property: MethodInfo methodInfo = propertyInfo.GetSetMethod(); ILout.Emit(OpCodes.Callvirt, methodInfo); break; } }