示例#1
0
        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]);
        }
示例#2
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()));
        }