public String Serialize(object obj)
        {
            SerializeState state = new SerializeState();

            this.Serialize(obj, state);

            return(state.sb.ToString());
        }
        //Serialize(object obj)

        private void Serialize(Object obj, SerializeState state)
        {
            StringBuilder sb = state.sb;

            if (obj == null)
            {
                sb.Append("N;");
            }
            else if (obj is string str)
            {
                if (XmlSafe)
                {
                    str = str.Replace("rn", "n");                    //replace rn with n
                    str = str.Replace("r", "n");                     //replace r not followed by n with a single n  Should we do this?
                }
                sb.Append("s:" + StringEncoding.GetByteCount(str) + ":" + str + ";");
            }
            else if (obj is bool b)
            {
                sb.Append("b:" + (b ? "1" : "0") + ";");
            }
            else if (obj is int objInt)
            {
                sb.Append("i:" + objInt.ToString(_nfi) + ";");
            }
            else if (obj is double objDbl)
            {
                sb.Append("d:" + objDbl.ToString(_nfi) + ";");
            }
            else if ((obj is IReadOnlyDictionary <object, object>) || (obj is IDictionary <object, object>))
            {
                if (state.seenCollections.Contains(obj))
                {
                    sb.Append("N;");
                }
                else
                {
                    state.seenCollections.Add(obj);

                    IEnumerable <KeyValuePair <Object, Object> > asDictEnum = (IEnumerable <KeyValuePair <Object, Object> >)obj;

                    sb.Append("a:" + asDictEnum.Count() + ":{");
                    foreach (var entry in asDictEnum)
                    {
                        this.Serialize(entry.Key, state);
                        this.Serialize(entry.Value, state);
                    }
                    sb.Append("}");
                }
            }
            else if (obj is IEnumerable <object> enumerable)
            {
                if (state.seenCollections.Contains(enumerable))
                {
                    sb.Append("N;");
                }
                else
                {
                    state.seenCollections.Add(enumerable);

                    IReadOnlyList <Object> asList = enumerable as IReadOnlyList <Object>;                   // T[] / Array<T> implements IReadOnlyList<T> already.
                    if (asList == null)
                    {
                        asList = enumerable.ToList();
                    }

                    sb.Append("a:" + asList.Count + ":{");

                    Int32 i = 0;
                    foreach (Object item in asList)
                    {
                        this.Serialize(i, state);
                        this.Serialize(item, state);

                        i++;
                    }

                    sb.Append("}");
                }
            }
            else
            {
                throw new SerializationException("Value could not be serialized.");
            }
        }