Icepack 1.2.0

dotnet add package Icepack --version 1.2.0
                    
NuGet\Install-Package Icepack -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Icepack" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Icepack" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Icepack" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Icepack --version 1.2.0
                    
#r "nuget: Icepack, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Icepack@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Icepack&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Icepack&version=1.2.0
                    
Install as a Cake Tool

ICEPACK

Icepack is a lightweight binary serialization library for C#.

It was originally developed for a game development project to address limitations that other serialization libraries have when serializing inheritance-based hierarchies, and to make it easy for code frameworks to implement serializable base classes.

Features

  • Object references are preserved by default, although this can be disabled globally.
  • The serializer serializes all fields by default, but can be configured to only serialize fields annotated with the SerializableField attribute. Fields can be ignored by the serializer by annotating them with the IgnoreField attribute.
  • The format slightly favours deserialization performance over serialization performance. This is often important for games since the end-user is usually more affected by load times.
  • Types can be included for serialization by calling the serializer's RegisterType method, or annotating the type with the SerializableType attribute.
  • Fields can be ignored by annotating them with the IgnoreField attribute.
  • The ISerializationListener interface is provided to allow classes and structs to execute additional logic before serialization and after deserialization.
  • Readonly fields are supported.
  • Interfaces are supported.
  • Boxed value types are supported.
  • The serializer can handle derived and base classes that define fields with the same name.
  • The serializer can call private constructors.
  • Arrays, and List<T>, HashSet<T>, and Dictionary<T> are registered automatically, but their generic parameter types must be registered explicitly.
  • Deserialization is somewhat resilient to changes to the data types since serialization:
    • Fields that have been added/removed to/from a class since serialization will be ignored.
    • A field that was serialized as a reference to an instance of a missing class is ignored.
    • If a class was derived from another class that is now missing or is no longer a base class, the missing or former base class is ignored, and the serializer resumes deserializing fields from other ancestors.
    • The PreviousName attribute can be assigned to a field to indicate that the name of the field has changed, so that the correct field will be matched with what is in the serialized data.
  • Surrogate types.

Limitations

  • Only fields (both private and public) are serialized, not properties.
  • nuint, nint, delegates, pointers, Span, and generic type definitions are not supported.
  • Deserializing after changing the type of a serialized field results in undefined behaviour.
  • Changing the name or namespace of a type will result in the serializer ignoring objects of that type.

Examples

Registering Types

Types must be registered before they can be serialized. Types can be lazy-registered by annotating them with the SerializableType attribute.

[SerializableType]
public class ExampleType { }

Types can also be registered via the serializer's RegisterType method. This is needed to serialize types defined in third-party libraries.

Serializer serializer = new();
serializer.RegisterType(typeof(ExampleType));

Serialization and Deserialization

The serializer serializes and deserializes an object graph to and from a stream.

Serializer serializer = new();

ExampleType obj = new();

MemoryStream stream = new();
serializer.Serialize(obj, stream);
stream.Position = 0;
ExampleType? deserializedObj = serializer.Deserialize<ExampleType>(stream);
stream.Close();

Serialization Callbacks

The ISerializationListener is used to execute logic immediately before serialization and after deserialization.

[SerializableType]
public class ExampleClass : ISerializationListener
{
  public int Field;

  public void OnBeforeSerialize()
  {
    Console.WriteLine("Before serializing.");
  }

  public void OnAfterDeserialize()
  {
    Console.WriteLine("After deserialized.");
  }
}

Surrogate Types

A type can be registered with a surrogate type which replaces the original type during serialization/deserialization. This is useful when you need to serialize types that you cannot modify. This feature has some limitations, including:

  • Only the surrogate of the object type is applied, surrogates of base types are not applied.
  • A surrogate of a reference type must be a reference type, while a surrogate of a value type must be a value type.
  • Surrogate types cannot have surrogate types.
  • A surrogate type cannot reference the original type.
[SerializableType]
internal struct SerializableStruct
{
  public int Field;
}

[SerializableType]
public struct SurrogateStruct : ISerializationSurrogate
{
  public int Field;

  public void Record(object obj)
  {
    SerializableStruct objToRecord = (SerializableStruct)obj;
    Field = objToRecord.Field;
  }

  public object Restore(object obj)
  {
    SerializableStruct objToRestore = (SerializableStruct)obj;
    objToRestore.Field = int.Parse(Field);
    return objToRestore;
  }
}

Serializer serializer = new();
serializer.RegisterType(typeof(SerializableStruct), typeof(SurrogateStruct));

SerializableStruct obj = new() { Field = 123 };

MemoryStream stream = new();
serializer.Serialize(obj, stream);
stream.Position = 0;
SerializableStruct? deserializedObj = serializer.Deserialize<SerializableStruct>(stream);
stream.Close();
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 140 12/15/2024
1.1.0 501 9/10/2022
1.0.8 510 7/21/2022
1.0.7 502 7/20/2022
1.0.6 509 7/18/2022
1.0.5 517 7/16/2022
1.0.4 495 10/9/2021
1.0.3 460 10/9/2021
1.0.2 411 10/5/2021
1.0.1 456 10/4/2021
1.0.0 421 10/4/2021

Surrogates.