示例#1
0
        public void Serialize(ref byte[] buffer, ref int offset, Person value)
        {
            SerializerBinary.WriteString(ref buffer, ref offset, value.Name);
            SerializerBinary.WriteInt32(ref buffer, ref offset, value.Health);
            PersonFormatter.Serialize(ref buffer, ref offset, value.BestFriend);

            // Important:
            // You might be tempted to just recursively call Serialize again for 'BestFriend', but that won't work!
            // Do not think you can manually serialize other instances.
            // It may look like that the object injected into "PersonFormatter" is just 'MyCustomPersonFormatter' itself again,
            // but that's not the case!
            // In fact, what you get is a lot of magic behind the scenes that deals with a ton of edge cases (object references, and reference loop handling, and more)
        }
示例#2
0
        public void Serialize(ref byte[] buffer, ref int offset, Person value)
        {
            SerializerBinary.WriteString(ref buffer, ref offset, value.Name);
            SerializerBinary.WriteInt32(ref buffer, ref offset, value.Health);

            // !! Important - Read below!
            PersonFormatter.Serialize(ref buffer, ref offset, value.BestFriend);

            // You might be tempted to just recursively call your own Serialize method (this method) again for 'BestFriend', but that won't work!
            // That won't work because Ceras does many things behind the scenes to make reference-loops work.
            //
            // Think about it like this:
            // When we want to serialize '.BestFriend' and someone is their own best friend (silly, i know :P) then we'd want the serialized data to
            // say "this object was already written, look it up here..."
            // Otherwise we'd get into an infinite loop, which is exactly what is happening if we'd just write "this.Serialize(ref buffer, ref offset, value.BestFriend);" here.
            //
            // Now, as for the 'PersonFormatter' field in this class.
            // Ceras can inject fields of type 'IFormatter' and 'CerasSerializer' into all its formatters.
            // So, even though it may look like that the object injected into "PersonFormatter" is just 'MyCustomPersonFormatter' itself again, that's not the case!
            //
            // In case you are interested in what's going on behind the scenes:
            // Ceras actually injects a 'ReferenceFormatter<Person>' into our 'PersonFormatter' field, which deals with reference loops.
        }
示例#3
0
        public void Serialize(ref byte[] buffer, ref int offset, Type type)
        {
            // Null
            if (type == null)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias);
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (typeCache.TryGetExistingObjectId(type, out int id))
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias);
                return;
            }


            // Mode: New


            // Is it a composite type that we have to split into its parts? (aka any generic)
            bool isClosed = !type.ContainsGenericParameters;

            if (isClosed && type.IsGenericType)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewGeneric, Bias);

                // Split and write

                // Base
                var baseType = type.GetGenericTypeDefinition();
                Serialize(ref buffer, ref offset, baseType);

                // Args
                var genericArgs = type.GetGenericArguments();

                SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(genericArgs.Length));                 // We need count. Ex: Action<T1> and Action<T1, T2> share the name
                for (int i = 0; i < genericArgs.Length; i++)
                {
                    Serialize(ref buffer, ref offset, genericArgs[i]);
                }

                // Register composite type
                typeCache.RegisterObject(type);
            }
            else
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewSingle, Bias);

                // Open generic, something that can be serialized alone
                var typeName = _typeBinder.GetBaseName(type);

                // Name
                SerializerBinary.WriteString(ref buffer, ref offset, typeName);

                // Register single type
                typeCache.RegisterObject(type);
            }

            // todo: do we put this only in the if or else part? or is it ok here? it should be ok, since we want to embed the schema of every type
            if (_serializer.Config.VersionTolerance == VersionTolerance.AutomaticEmbedded)
            {
                if (!CerasSerializer.FrameworkAssemblies.Contains(type.Assembly))
                {
                    _serializer.WriteSchemaForType(ref buffer, ref offset, type);
                }
            }
        }
示例#4
0
        public void Serialize(ref byte[] buffer, ref int offset, Type type)
        {
            // Null
            if (type == null)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias);
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (typeCache.TryGetExistingObjectId(type, out int id))
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias);
                return;
            }


            // Mode: New


            // Is it a composite type that we have to split into its parts? (aka any generic)
            bool isClosed = !type.ContainsGenericParameters;

            if (isClosed && type.IsGenericType)
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewComposite, Bias);

                // Split and write

                // Base
                var baseType = type.GetGenericTypeDefinition();
                Serialize(ref buffer, ref offset, baseType);


                // Args
                var genericArgs = type.GetGenericArguments();

                SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(genericArgs.Length));                 // We need count. Ex: Action<T1> and Action<T1, T2> share the name.
                for (int i = 0; i < genericArgs.Length; i++)
                {
                    Serialize(ref buffer, ref offset, genericArgs[i]);
                }


                // Register composite type
                typeCache.RegisterObject(type);
            }
            else
            {
                SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewSingle, Bias);

                // Open generic, something that can be serialized alone

                var typeName = _typeBinder.GetBaseName(type);

                // Name
                SerializerBinary.WriteString(ref buffer, ref offset, typeName);


                // Register single type
                typeCache.RegisterObject(type);
            }
        }
示例#5
0
        public void Serialize(ref byte[] buffer, ref int offset, T value)
        {
            var str = value.ToString();

            SerializerBinary.WriteString(ref buffer, ref offset, str);
        }
示例#6
0
 public void Serialize(ref byte[] buffer, ref int offset, string value)
 {
     SerializerBinary.WriteString(ref buffer, ref offset, value);
 }
示例#7
0
 public void Serialize(ref byte[] buffer, ref int offset, Uri value)
 {
     SerializerBinary.WriteString(ref buffer, ref offset, value.OriginalString);
 }