/// <summary>
        /// Creates the list of property setters for a reader.
        /// </summary>
        /// <param name="type">The type of object to map to.</param>
        /// <param name="reader">The reader to read.</param>
        /// <param name="command">The command that is currently being mapped.</param>
        /// <param name="parameters">The list of parameters used in the mapping operation.</param>
        /// <param name="structure">The structure of the record being read.</param>
        /// <param name="startColumn">The index of the first column to map.</param>
        /// <param name="columnCount">The number of columns to map.</param>
        /// <param name="uniqueMatches">True to only return the first match per field, false to return all matches per field.</param>
        /// <returns>An array of setters.</returns>
        internal ColumnMappingEventArgs[] CreateMapping(
            Type type,
            IDataReader reader,
            IDbCommand command,
            IList <IDataParameter> parameters,
            IRecordStructure structure,
            int startColumn,
            int columnCount,
            bool uniqueMatches)
        {
            ColumnMappingEventArgs[] mapping = new ColumnMappingEventArgs[columnCount];

            // convert the list of names into a list of set reflections
            // clone the methods list, since we are only going to use each setter once (i.e. if you return two ID columns, we will only use the first one)
            // Also, we want to do a case-insensitive lookup of the property, so convert the dictionary to an uppercase dictionary
            var setMethods = new Dictionary <string, ClassPropInfo>(ClassPropInfo.GetMappingForType(type), StringComparer.OrdinalIgnoreCase);

            List <IDataParameter> readOnlyParameters = null;

            if (parameters != null)
            {
                readOnlyParameters = new List <IDataParameter>(parameters.OfType <IDataParameter>().ToList());
            }

            // find all of the mappings
            for (int i = 0; i < columnCount; i++)
            {
                // generate an event
                var e = new ColumnMappingEventArgs()
                {
                    TargetType = type,
                    Reader     = reader,
                    FieldIndex = i + startColumn,
                    Parameters = readOnlyParameters,
                };

                if (command != null)
                {
                    e.CommandText = command.CommandText;
                    e.CommandType = command.CommandType;
                }

                if (reader != null)
                {
                    e.ColumnName = reader.GetSchemaTable().Rows[e.FieldIndex]["ColumnName"].ToString();
                }

                lock (_lock)
                {
                    _mappings(null, e);
                }

                // if no mapping was returned, then skip the column
                if (e.Canceled || String.IsNullOrEmpty(e.TargetFieldName.Trim()))
                {
                    continue;
                }

                // if a column mapping override was specified, then attempt an override
                if (structure != null)
                {
                    structure.MapColumn(e);
                }

                // get the target property based on the result
                string targetFieldName = e.TargetFieldName;

                // first see if there is a wildcard column, if not, then look up the field name
                ClassPropInfo setter;
                if (setMethods.TryGetValue("*", out setter) ||
                    setMethods.TryGetValue(targetFieldName, out setter))
                {
                    mapping[i]      = e;
                    e.ClassPropInfo = setter;

                    InitializeMappingSerializer(e, reader, command, parameters, i);

                    // remove the name from the list so we can only use it once
                    if (uniqueMatches)
                    {
                        setMethods.Remove(setter.ColumnName);
                    }
                }
            }

            return(mapping);
        }