/// <summary>
        /// Serializes a dictionary.
        /// </summary>
        /// <param name="obj">The dictionary to serialize.</param>
        /// <param name="useSB">Whether this will write to a string builder (if true), or return a string (if false).</param>
        /// <param name="sb">The StringBuilder to write to - if <paramref name="useSB"/> is true.</param>
        /// <param name="dnWriteEndLevel">"Do Not Write End Level Symbol" - Marks whether to NOT write \u0005 (if true), commonly used for the last object of all.</param>
        /// <returns>If <paramref name="useSB"/> is false, this method will return the result as a string.</returns>
        public static string SerializeDictionary(dynamic obj, ABSaveType type, ABSaveSettings settings, bool useSB = false, StringBuilder sb = null, bool dnWriteEndLevel = false)
        {
            // Create a variable to store what we'll return.
            var ret = "";

            // Keep track of whether we're on the first item or not.
            var notFirst = false;

            // Write the opening for the array.
            ret += ABSaveWriter.WriteDictionaryOpening(useSB, sb);

            // Now, go through each item in the dictionary.
            foreach (var element in obj)
            {
                // If this isn't the first item, write the "next item" character.
                if (notFirst)
                {
                    ret += ABSaveWriter.WriteNextItem(true, useSB, sb);
                }

                // Add the key to it.
                if (useSB)
                {
                    sb.Append(element.Key);
                }
                else
                {
                    ret += element.Key;
                }

                // Serialize the item and write to either the StringBuilder or the "ret"
                ret += Serialize(element.Value, type, settings, useSB, sb, true, dnWriteEndLevel);

                // Update the "notFirst" variable if needed.
                if (!notFirst)
                {
                    notFirst = true;
                }
            }

            // Write the closing for the dictionary.
            ret += ABSaveWriter.WriteObjectClose(dnWriteEndLevel, useSB, sb);

            // Now, "ret" would be empty if we were using a StringBuilder, however, if we weren't... It will have the correct string in it so return it.
            return(ret);
        }
        /// <summary>
        /// An object (with multiple properties) to serialize manually - one that doesn't have a TypeConverter.
        /// </summary>
        /// <param name="obj">The object to serialize manually</param>
        /// <param name="objType">The type of the object.</param>
        /// <param name="useSB">Whether this will write to a string builder (if true), or return a string (if false).</param>
        /// <param name="sb">The StringBuilder to write to - if <paramref name="useSB"/> is true.</param>
        /// <param name="dnWriteEndLevel">"Do Not Write End Level Symbol" - Marks whether to NOT write \u0005 (if true), commonly used for the last object of all.</param>
        /// <returns>If <paramref name="useSB"/> is false, this method will return the result as a string.</returns>
        public static string SerializeArray(dynamic obj, Type objType, ABSaveType type, ABSaveSettings settings, bool useSB = false, StringBuilder sb = null, bool dnWriteEndLevel = false)
        {
            obj = obj as IEnumerable;

            // Create a variable to store what we'll return.
            var ret = "";

            // Keep track of whether we're on the first item or not.
            var notFirst = false;

            // Write the opening for the array.
            ret += ABSaveWriter.WriteArrayOpening(useSB, sb);

            // Keep track of what type the last property was - this allows us to decide whether to add the Next Item character to the next item.
            var lastType = ABSavePrimitiveType.Unknown;

            // If it's an array, just use a "for" loop.
            if (objType.IsArray)
            {
                for (var i = 0; i < obj.Length; i++)
                {
                    SerializeArrayItem(type, settings, useSB, sb, dnWriteEndLevel, ref ret, ref notFirst, ref lastType, obj[i]);
                }
            }

            // For anything else, foreach will work fine.
            else
            {
                foreach (var item in obj)
                {
                    SerializeArrayItem(type, settings, useSB, sb, dnWriteEndLevel, ref ret, ref notFirst, ref lastType, item);
                }
            }

            // Write the closing for the array.
            ret += ABSaveWriter.WriteObjectClose(dnWriteEndLevel, useSB, sb);

            // Now, "ret" would be empty if we were using a StringBuilder, however, if we weren't... It will have the correct string in it so return it.
            return(ret);
        }
        /// <summary>
        /// Serializes an object, by using <see cref="ABSaveConvert"/>, but some extras.
        /// </summary>
        /// <param name="obj">The object to serialize manually.</param>
        /// <param name="objType">The type of the object to serialize manually.</param>
        /// <param name="useSB">Whether this will write to a string builder (if true), or return a string (if false).</param>
        /// <param name="sb">The StringBuilder to write to - if <paramref name="useSB"/> is true.</param>
        /// <param name="dnWriteEndLevel">"Do Not Write End Level Symbol" - Marks whether to NOT write \u0005 (if true), commonly used for the last object of all.</param>
        /// <param name="settings">The settings for how to handle certain parts.</param>
        /// <returns>If <paramref name="useSB"/> is false, this method will return the result as a string.</returns>
        public static string SerializeObject(object obj, ABSaveType type, Type objType, ABSaveSettings settings, bool writeNextInstructionSymbol = true, bool useSB = false, StringBuilder sb = null, bool dnWriteEndLevel = false)
        {
            // Create a variable to store what we'll return - if we aren't using a StringBuilder.
            var ret = "";

            // First, write a "next step" symbol.
            ret += ABSaveWriter.WriteNextItem(writeNextInstructionSymbol, useSB, sb);

            // Next, serialize the type that goes before it.
            ret += SerializeTypeBeforeObject(objType, settings, useSB, sb);

            // Then, write the opening (\u0003) for the object.
            ret += ABSaveWriter.WriteObjectOpen(useSB, sb);

            // And, write the actual object, use the correct method for either string or for a StringBuilder.
            ret += ABSaveConvert.ObjectToABSave(obj, type, settings, useSB, sb);

            // Finally, write the ending for the object.
            ret += ABSaveWriter.WriteObjectClose(dnWriteEndLevel, useSB, sb);

            // Now, "ret" would be empty if we were using a StringBuilder, however, if we weren't... It will have the correct string in it so return it.
            return(ret);
        }