Example #1
0
        /// <summary>
        /// Creates a deserializer to deserialize an object from an IDataReader.
        /// </summary>
        /// <param name="reader">The reader to analyze.</param>
        /// <param name="type">The type of object to deserialize from the IDataReader.</param>
        /// <param name="structure">The structure of the object.</param>
        /// <param name="mappingType">The type of mapping to create.</param>
        /// <returns>
        /// A function that takes an IDataReader and deserializes an object of type T.
        /// The first parameter will be an IDataReader.
        /// If createNewObject is true, the next parameter will be of type T.
        /// If useCallback is true, the next parameter will be an Action&lt;object[]&gt;.
        /// </returns>
        public static Delegate CreateDeserializer(IDataReader reader, Type type, IRecordStructure structure, SchemaMappingType mappingType)
        {
            // process the object graph types
            var subTypes = structure.GetObjectTypes();

            if (subTypes[0] != type)
            {
                throw new ArgumentException("The top-level type of the object graph must match the return type of the object.", "structure");
            }

            // if the graph type is not a graph, or just the object, and we don't want a callback function
            // then just return a one-level graph.
            if (subTypes.Length == 1 && !mappingType.HasFlag(SchemaMappingType.WithCallback))
            {
                return(CreateClassDeserializer(type, reader, structure, 0, (reader.IsClosed) ? 0 : reader.FieldCount, mappingType.HasFlag(SchemaMappingType.NewObject)));
            }

            // we can't deserialize an object graph in an insert/merge because we don't know whether to create subobjects or leave them null.
            if (!mappingType.HasFlag(SchemaMappingType.NewObject))
            {
                throw new ArgumentException("mappingType must be set to NewObject when deserializing an object graph.", "mappingType");
            }

            // create the graph deserializer
            if (mappingType.HasFlag(SchemaMappingType.WithCallback))
            {
                return(CreateGraphDeserializerWithCallback(subTypes, reader, structure, mappingType == SchemaMappingType.ExistingObject));
            }
            else
            {
                return(CreateGraphDeserializer(subTypes, reader, structure, mappingType == SchemaMappingType.ExistingObject));
            }
        }
        /// <summary>
        /// Get a deserializer to read class T from the given reader.
        /// </summary>
        /// <param name="reader">The reader to read from.</param>
        /// <param name="type">The type of object to deserialize.</param>
        /// <param name="structure">The structure of the objects in the record.</param>
        /// <param name="mappingType">The type of mapping to return.</param>
        /// <returns>A function that can deserialize a T from the reader.</returns>
        private static Delegate GetDeserializer(IDataReader reader, Type type, IRecordStructure structure, SchemaMappingType mappingType)
        {
            if (structure == null)
            {
                throw new ArgumentNullException("structure");
            }

            // This method should try to return the deserializer with as little work as possible.
            // Calculating the SchemaMappingIdentity is relatively expensive, so we will take care of the simple cases first,
            // Where we can just look up a type in a dictionary.
            // since these types are single column types, deserializing these types do not depend on the schema that comes back from the database
            // we don't need to keep a schema identity for these
            Delegate deserializer = null;

            if (!_simpleDeserializers.TryGetValue(type, out deserializer) && TypeHelper.IsAtomicType(type))
            {
                deserializer = GetValueDeserializer(type);
            }

            // we have a simple deserializer
            if (deserializer != null)
            {
                var genericArgs = structure.GetObjectTypes();
                if (genericArgs.Length != 1 || genericArgs[0] != type)
                {
                    throw new ArgumentException("Column Mapper does not match single column deserialization", "structure");
                }
                return(deserializer);
            }

            // at this point, we know that we aren't returning a value type or simple object that doesn't depend on the schema.
            // so we need to calculate a mapping identity and then create or return a deserializer.
            SchemaMappingIdentity identity = new SchemaMappingIdentity(reader, structure, mappingType);

            // try to get the deserializer. if not found, create one.
            return(_deserializers.GetOrAdd(
                       identity,
                       key => ClassDeserializerGenerator.CreateDeserializer(reader, type, structure, mappingType)));
        }
		/// <summary>
		/// Creates a deserializer to deserialize an object from an IDataReader.
		/// </summary>
		/// <param name="reader">The reader to analyze.</param>
		/// <param name="type">The type of object to deserialize from the IDataReader.</param>
		/// <param name="structure">The structure of the object.</param>
		/// <param name="mappingType">The type of mapping to create.</param>
		/// <returns>
		/// A function that takes an IDataReader and deserializes an object of type T.
		/// The first parameter will be an IDataReader.
		/// If createNewObject is true, the next parameter will be of type T.
		/// If useCallback is true, the next parameter will be an Action&lt;object[]&gt;.
		/// </returns>
		public static Delegate CreateDeserializer(IDataReader reader, Type type, IRecordStructure structure, SchemaMappingType mappingType)
		{
			// process the object graph types
			var subTypes = structure.GetObjectTypes();
			if (subTypes[0] != type)
				throw new ArgumentException("The top-level type of the object graph must match the return type of the object.", "structure");

			// if the graph type is not a graph, or just the object, and we don't want a callback function
			// then just return a one-level graph.
			if (subTypes.Length == 1 && !mappingType.HasFlag(SchemaMappingType.WithCallback))
				return CreateClassDeserializer(type, reader, structure, 0, (reader.IsClosed) ? 0 : reader.FieldCount, mappingType.HasFlag(SchemaMappingType.NewObject));

			// we can't deserialize an object graph in an insert/merge because we don't know whether to create subobjects or leave them null.
			if (!mappingType.HasFlag(SchemaMappingType.NewObject))
				throw new ArgumentException("mappingType must be set to NewObject when deserializing an object graph.", "mappingType");

			// create the graph deserializer
			if (mappingType.HasFlag(SchemaMappingType.WithCallback))
				return CreateGraphDeserializerWithCallback(subTypes, reader, structure);
			else
				return CreateGraphDeserializer(subTypes, reader, structure);
		}