예제 #1
0
        public void Serialize(ref byte[] buffer, ref int offset, T value)
        {
            if (EqualityComparer <T> .Default.Equals(value, default))
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias);
                return;
            }

            if (value is Type type)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, InlineType, Bias);
                _typeFormatter.Serialize(ref buffer, ref offset, type);
                return;
            }

            if (value is IExternalRootObject externalObj)
            {
                if (!object.ReferenceEquals(_serializer.InstanceData.CurrentRoot, value))
                {
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, ExternalObject, Bias);

                    var refId = externalObj.GetReferenceId();
                    SerializerBinary.WriteInt32(ref buffer, ref offset, refId);

                    _serializer.Config.OnExternalObject?.Invoke(externalObj);

                    return;
                }
            }

            if (_serializer.InstanceData.ObjectCache.TryGetExistingObjectId(value, out int id))
            {
                // Existing value
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias);
            }
            else
            {
                // Important: Insert the ID for this value into our dictionary BEFORE calling SerializeFirstTime, as that might recursively call us again (maybe with the same value!)
                _serializer.InstanceData.ObjectCache.RegisterObject(value);

                var specificType = value.GetType();
                if (typeof(T) == specificType)
                {
                    // New value (same type)
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValueSameType, Bias);
                }
                else
                {
                    // New value (type included)
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValue, Bias);
                    _typeFormatter.Serialize(ref buffer, ref offset, specificType);
                }

                // Write the object normally
                GetSpecificSerializerDispatcher(specificType)(ref buffer, ref offset, value);
            }
        }
예제 #2
0
        public void Serialize(ref byte[] buffer, ref int offset, T value)
        {
            if (ReferenceEquals(value, null))
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias);
                return;
            }

            var specificType = value.GetType();
            var entry        = GetOrCreateEntry(specificType);

            if (entry.IsType)             // This is very rare, so we cache the check itself, and do the cast below
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, InlineType, Bias);
                _typeFormatter.Serialize(ref buffer, ref offset, (Type)(object)value);
                return;
            }

            if (entry.IsExternalRootObject)
            {
                var externalObj = (IExternalRootObject)value;

                if (!ReferenceEquals(_ceras.InstanceData.CurrentRoot, value))
                {
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, ExternalObject, Bias);

                    var refId = externalObj.GetReferenceId();
                    SerializerBinary.WriteInt32(ref buffer, ref offset, refId);

                    _ceras.Config.OnExternalObject?.Invoke(externalObj);

                    return;
                }
            }

            if (_allowReferences)
            {
                if (_ceras.InstanceData.ObjectCache.TryGetExistingObjectId(value, out int id))
                {
                    // Existing value
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias);
                }
                else
                {
                    // Register new object
                    _ceras.InstanceData.ObjectCache.RegisterObject(value);

                    // Embedd type (if needed)
                    if (ReferenceEquals(typeof(T), specificType))
                    {
                        // New value (same type)
                        SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValueSameType, Bias);
                    }
                    else
                    {
                        // New value (type included)
                        SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValue, Bias);
                        _typeFormatter.Serialize(ref buffer, ref offset, specificType);
                    }

                    // Write object
                    entry.CurrentSerializeDispatcher(ref buffer, ref offset, value);
                }
            }
            else
            {
                // Embedd type (if needed)
                if (ReferenceEquals(typeof(T), specificType))
                {
                    // New value (same type)
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValueSameType, Bias);
                }
                else
                {
                    // New value (type included)
                    SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValue, Bias);
                    _typeFormatter.Serialize(ref buffer, ref offset, specificType);
                }

                // Write object
                entry.CurrentSerializeDispatcher(ref buffer, ref offset, value);
            }
        }