You are here: Start » FIL.NET » Serialization

Serialization

  1. Introduction
  2. Byte array
  3. User types
  4. Reader and Writer
  5. Native memory

Introduction

Serialization and deserialization in FIL.NET are accessible via the static methods of the Fis.Serializer. All examples presented in this article utilize the same using directives:

using Fil;
using Fil.Serialization;
using FluentAssertions;
using System;
using Xunit;
using static Fil.Invoke;

Byte array

Serialization to and from a byte[] instance is performed using the Fis.Serializer.Serialize<T> and Fis.Serializer.Deserialize<T> methods:

[Fact]
public void With_byte_array()
{
    // prepare an image
    using Image inputImage = new();
    EmptyImage(100, 100, Pixel.Red, 3, PlainType.UInt8, inputImage);

    // serialize
    byte[] bytes = Fis.Serializer.Serialize(inputImage);

    // deserialize
    using Image deserializedImage = Fis.Serializer.Deserialize<Image>(bytes);

    // validate
    deserializedImage.Should().Be(inputImage); // Equals
}

User types

User-defined types are serialized when they are marked with the Fil.Serialization.FilObjectAttribute. By default, all public and non-public instance properties and fields are serialized. Members marked with the Fil.Serialization.FilIgnoreAttribute attribute, are excluded from the serialization.

[FilObject]
class MyClass
{
    public Image? Image { get; set; }

    public Point2D Point { get; set; }

    [FilIgnore]
    public int Value { get; set; }
}

[Fact]
public void User_type()
{
    // prepare the data to be serialized
    using Image image = new();
    EmptyImage(100, 100, Pixel.Red, 3, PlainType.UInt8, image);

    MyClass mc = new()
    {
        Image = image,
        Point = new Point2D(1, 2),
        Value = 24
    };

    // serialize
    byte[] bytes = Fis.Serializer.Serialize(mc);

    // deserialize
    MyClass deserialized = Fis.Serializer.Deserialize<MyClass>(bytes);

    // validate
    deserialized.Image.Should().Be(mc.Image);
    deserialized.Point.Should().Be(mc.Point);
    deserialized.Value.Should().Be(0); // ignored during serialization
}

Reader and Writer

Expandable memory block can be used as a serialization target instead of the byte array so serializing multiple objects to the same block is possible. This can be achieved with Ftl.BinaryReader and Ftl.BinaryWriter types.

An expandable memory block can be used as a serialization target instead of a byte array, allowing for multiple objects to be serialized to the same block. This can be accomplished using the Ftl.BinaryReader and Ftl.BinaryWriter types.

[Fact]
public void With_reader_and_writer()
{
    // prepare an image
    using Image image = new();
    EmptyImage(100, 100, Pixel.Red, 3, PlainType.UInt8, image);

    // prepare the buffer and writer
    using Ftl.ByteArray bytes = new();
    using Ftl.BinaryWriter writer = new(bytes, Ftl.BinaryMode.EXTERNAL);

    // serialize
    Fis.Serializer.WriteData(writer, image);

    // prepare the reader
    using Ftl.BinaryReader reader = new(bytes.Begin);

    // deserialize
    using Image deserialized = Fis.Serializer.ReadData<Image>(reader);

    // validate
    deserialized.Should().Be(image);
}

Native memory

Objects can be deserialized directly from a System.IntPtr instance.

[Fact]
public void With_ptr()
{
    // prepare a serialized image in the memory
    using Image image = new();
    EmptyImage(100, 100, Pixel.Red, 3, PlainType.UInt8, image);
    using Ftl.BinaryWriter writer = new(Ftl.BinaryMode.EXTERNAL);
    Fis.Serializer.WriteData(writer, image);
    IntPtr data = writer.Data;

    // read from native memory
    using Image deserialized = Fis.Serializer.ReadData<Image>(data);

    // validate
    deserialized.Should().Be(image);
}
Previous: Relation between FIL.NET and FIL/C++ Next: FIL.NET Designers