/**
         * Process a single object to be pickled.
         */
        private bool dispatch(Type t, object o)
        {
            Debug.Assert(t != null);
            Debug.Assert(o != null);
            Debug.Assert(t == o.GetType());

            // is it a primitive array?
            if (o is Array)
            {
                Type componentType = t.GetElementType();
                if (componentType != null && componentType.IsPrimitive)
                {
                    put_arrayOfPrimitives(componentType, o);
                }
                else if (o is string[] strings)
                {
                    put_arrayOfStrings(strings);
                }
                else
                {
                    put_arrayOfObjects((object[])o);
                }
                return(true);
            }

            if (t.IsPrimitive)
            {
                switch (o)
                {
                case double v:
                    put_float(v);
                    return(true);

                case int v:
                    put_long(v);
                    return(true);

                case bool v:
                    put_bool(v);
                    return(true);

                case float v:
                    put_float(v);
                    return(true);

                case long v:
                    put_long(v);
                    return(true);

                case byte v:
                    put_byte(v);
                    return(true);

                case sbyte v:
                    put_long(v);
                    return(true);

                case short v:
                    put_long(v);
                    return(true);

                case ushort v:
                    put_long(v);
                    return(true);

                case uint v:
                    put_long(v);
                    return(true);

                case ulong v:
                    put_ulong(v);
                    return(true);

                case char v:
                    put_string(v.ToString());
                    return(true);
                }
            }
            else
            {
                switch (o)
                {
                case string v:
                    put_string(v);
                    return(true);

                case Enum v:
                    put_string(o.ToString());
                    return(true);

                case decimal v:
                    put_decimal(v);
                    return(true);

                case DateTime v:
                    put_datetime(v);
                    return(true);

                case TimeSpan v:
                    put_timespan(v);
                    return(true);

                case IDictionary v:
                    put_map(v);
                    return(true);

                case IList v:
                    put_enumerable(v);
                    return(true);

                case IEnumerable v:
                    if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(HashSet <>))
                    {
                        put_set(v);
                    }
                    else
                    {
                        put_enumerable(v);
                    }
                    return(true);
                }
            }

            // check registry
            IObjectPickler custompickler = pickler.getCustomPickler(t);

            if (custompickler != null)
            {
                // to support this scenario this type derives from Stream and implements Write methods
                custompickler.pickle(o, this, pickler);
                WriteMemo(o);
                return(true);
            }

            // more complex types
            DataContractAttribute dca = (DataContractAttribute)Attribute.GetCustomAttribute(t, typeof(DataContractAttribute));

            if (dca != null)
            {
                put_datacontract(t, o, dca);
                return(true);
            }

            SerializableAttribute sa = (SerializableAttribute)Attribute.GetCustomAttribute(t, typeof(SerializableAttribute));

            if (sa != null)
            {
                put_serializable(t, o);
                return(true);
            }

            if (hasPublicProperties(t))
            {
                put_objwithproperties(o);
                return(true);
            }

            return(false);
        }