public static AdoProviderMetadata GetMetadata(Type connectionType) { var adoProviderMetadataItemsCopy = adoProviderMetadataItems; for (var index = 0; index < adoProviderMetadataItemsCopy.Length; index++) { var adoProvideMetadata = adoProviderMetadataItemsCopy[index]; if (ReferenceEquals(adoProvideMetadata.connectionType, connectionType)) { return(adoProvideMetadata); } } var newAdoProviderMetadataItems = new AdoProviderMetadata[adoProviderMetadataItemsCopy.Length + 1]; Array.Copy(adoProviderMetadataItemsCopy, 0, newAdoProviderMetadataItems, 1, adoProviderMetadataItemsCopy.Length); newAdoProviderMetadataItems[0] = new AdoProviderMetadata(connectionType); adoProviderMetadataItems = newAdoProviderMetadataItems; return(newAdoProviderMetadataItems[0]); }
internal static DataReaderDeserializer Create(Type connectionType, Type type, string[] columnNames, Type[] columnTypes) { var adoProviderMetadata = AdoProviderMetadata.GetMetadata(connectionType); var dataReaderMetadata = adoProviderMetadata.DataReaderMetadata; var moduleBuilder = DynamicAssembly.GetExistingDynamicAssemblyOrCreateNew(type.Assembly); var enumeratorType = typeof(IEnumerator <>).MakeGenericType(type); var enumerableType = typeof(IEnumerable <>).MakeGenericType(type); var dataReaderDeserializerType = typeof(DataReaderDeserializer); var typeName = DynamicAssembly.GetUniqueTypeName("DbMap.Runtime." + type.Name + nameof(DataReaderDeserializer)); var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Sealed, dataReaderDeserializerType, new[] { enumeratorType, enumerableType }); var fieldMap = new FieldMap(typeBuilder); // Fields var readerField = typeBuilder.DefineField("reader", DbDataReaderType, FieldAttributes.Private); var commandField = typeBuilder.DefineField("command", typeof(DbCommand), FieldAttributes.Private); // .ctor() { var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); var il = constructor.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Ret); } // .ctor(DbCommand, DbDataReader) var dataReaderDeserializerConstructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, DeserializeAllParameters); { var il = dataReaderDeserializerConstructor.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, commandField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Stfld, readerField); il.Emit(OpCodes.Ret); } // Reset() { var method = typeBuilder.DefineMethod("Reset", MethodAttributes.Public | MethodAttributes.Virtual); var il = method.GetILGenerator(); il.ThrowException(typeof(NotSupportedException)); il.Emit(OpCodes.Ret); } // Dispose() { var method = typeBuilder.DefineMethod("Dispose", MethodAttributes.Public | MethodAttributes.Virtual); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, readerField); il.Emit(OpCodes.Call, dataReaderMetadata.DisposeMethod); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, commandField); il.Emit(OpCodes.Call, DbCommandMetadata.Dispose); il.Emit(OpCodes.Ret); } // MoveNext() { var method = typeBuilder.DefineMethod("MoveNext", MethodAttributes.Public | MethodAttributes.Virtual, typeof(bool), Type.EmptyTypes); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, readerField); il.Emit(OpCodes.Call, dataReaderMetadata.ReadMethod); il.Emit(OpCodes.Ret); } // TReturn Deserialize<TReturn>(DBDataReader) var deserializeMethod = typeBuilder.DefineMethod(nameof(DataReaderDeserializer.Deserialize), MethodAttributes.Public | MethodAttributes.Virtual); { var returnTypeParameter = deserializeMethod.DefineGenericParameters("TReturn")[0]; deserializeMethod.SetReturnType(returnTypeParameter); deserializeMethod.SetParameters(DbDataReaderTypeArray); var il = deserializeMethod.GetILGenerator(); EmitDeserializeType(dataReaderMetadata, fieldMap, il, type, columnNames, columnTypes); il.Emit(OpCodes.Ret); } // IEnumerable<TReturn> DeserializeAll<TReturn>(DbCommand, DbDataReader) { var deserializeAllMethod = typeBuilder.DefineMethod(nameof(DataReaderDeserializer.DeserializeAll), MethodAttributes.Public | MethodAttributes.Virtual); var returnTypeParameter = deserializeAllMethod.DefineGenericParameters("TReturn")[0]; deserializeAllMethod.SetReturnType(typeof(IEnumerable <>).MakeGenericType(returnTypeParameter)); deserializeAllMethod.SetParameters(DeserializeAllParameters); var il = deserializeAllMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Newobj, dataReaderDeserializerConstructor); il.Emit(OpCodes.Ret); } // TReturn Current { get; } { var property = typeBuilder.DefineProperty("Current", PropertyAttributes.None, type, Type.EmptyTypes); var propertyGet = typeBuilder.DefineMethod("get_Current", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual, type, Type.EmptyTypes); var il = propertyGet.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, readerField); il.Emit(OpCodes.Call, deserializeMethod.MakeGenericMethod(type)); il.Emit(OpCodes.Ret); property.SetGetMethod(propertyGet); } // object Current { get; } { var property = typeBuilder.DefineProperty("Current", PropertyAttributes.HasDefault, typeof(object), Type.EmptyTypes); var propertyGet = typeBuilder.DefineMethod("get_Current", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual, typeof(object), Type.EmptyTypes); var il = propertyGet.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, readerField); il.Emit(OpCodes.Call, deserializeMethod.MakeGenericMethod(type)); il.Emit(OpCodes.Castclass, typeof(object)); il.Emit(OpCodes.Ret); property.SetGetMethod(propertyGet); } // IEnumerator<TReturn> GetEnumerator() { var method = typeBuilder.DefineMethod("GetEnumerator", MethodAttributes.Public | MethodAttributes.Virtual, enumeratorType, Type.EmptyTypes); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ret); } // IEnumerator GetEnumerator() { var method = typeBuilder.DefineMethod("GetEnumerator", MethodAttributes.Public | MethodAttributes.Virtual, typeof(IEnumerator), Type.EmptyTypes); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, typeof(IEnumerator)); il.Emit(OpCodes.Ret); } return((DataReaderDeserializer)Activator.CreateInstance(typeBuilder.CreateTypeInfo())); }