How to Store Serializer Definitions Alongside Your Data
A binary payload is only useful when its reader knows how to interpret it. Applications usually keep that knowledge in code: which CLR types exist, which serializer belongs to each type and how a composite record's members are arranged. When construction metadata is part of the storage problem, Sphere10 can encode a reconstructible serializer factory rather than relying solely on a separately recreated registry.
We will keep two byte arrays: one describing the factory and one containing a small record. A fresh factory is reconstructed first, then used to decode the record. The distinction is intentional. Factory metadata describes supported serialization machinery. It is not the record itself, a captured delegate or a replacement for the application's types.
Contents
What a Factory Describes
A SerializerFactory maps data types to serializer registrations and their type codes. Composite registrations can also describe the member bindings needed to encode an object. Those choices matter when bytes need to be interpreted later. An application that silently changes type codes or member order has changed its format, even if the class still has a familiar name.
SerializerFactorySerializer preserves the supported registration information required to construct another factory. The codec stores declarative information, not executable closures. The CLR data and serializer types must still be available to the reader. This is closer to carrying a construction recipe than shipping a second copy of the application's runtime.
Keep Application Registrations Local
Start with an application-owned factory copied from the Framework defaults. Register the application's record there, instead of modifying the global default factory for every consumer in the process. The sample also selects a generated type-code starting boundary deliberately. That helps illustrate that application codes are real format choices, not invisible implementation details.
The record is deliberately plain:
namespace ArticleSample;
public sealed class StoredItem {
public long Value { get; set; }
public string Name { get; set; }
}
A public parameterless constructor and writable members fit automatic assembly. For a long-lived interchange format, review the exact selected members and compatibility plan. An automatic reflection scan does not promise that future versions of a renamed or expanded class can read an older payload without an explicit migration.
Write Metadata and Payload Separately
using System;
using Sphere10.Framework;
namespace ArticleSample;
public static class Program {
public static void Main() {
// Keep application registrations local and choose the byte order explicitly.
var factory = new SerializerFactory(SerializerFactory.Default)
.SetMinTypeCode(2100)
.RegisterAutoBuild<StoredItem>();
var factorySerializer = new SerializerFactorySerializer();
var factoryBytes = factorySerializer.SerializeToBytes(factory, Endianness.LittleEndian);
var originalSerializer = factory.GetSerializer<StoredItem>();
var payload = originalSerializer.SerializeToBytes(new StoredItem { Value = 42, Name = "catalogue" }, Endianness.LittleEndian);
// A fresh factory is reconstructed before the separate payload is decoded.
var restoredFactory = factorySerializer.DeserializeBytes(factoryBytes, Endianness.LittleEndian);
var restoredSerializer = restoredFactory.GetSerializer<StoredItem>();
var item = restoredSerializer.DeserializeBytes(payload, Endianness.LittleEndian);
if (item.Value != 42 || item.Name != "catalogue")
throw new InvalidOperationException("The reconstructed serializer differs.");
Console.WriteLine($"Restored item: {item.Name} = {item.Value}");
Console.WriteLine($"Factory and payload are separate: {factoryBytes.Length > 0 && payload.Length > 0}");
}
}
The original serializer writes the data. The factory codec writes the registry description. We then discard the idea that the first live factory is available and reconstruct a fresh one from factoryBytes. Only the restored factory supplies the serializer used for the payload read. That sequence tests the capability the article is teaching rather than accidentally decoding through the still-live original registration.
The expected result is:
Restored item: catalogue = 42
Factory and payload are separate: True
The sample asserts both fields and checks that the metadata and data are nonempty separate records. A stronger application-specific test would close its complete container, reopen a fresh process and perform the same reconstruction with only the supported type assemblies and format description available.
Know Which Configuration Can Travel
Ordinary supported registrations, automatic composite layouts and their exact type codes can be reconstructed. A custom serializer's ordinary constructor must recreate its deterministic configuration. Independently mutating a serializer instance after construction is a different situation because the codec does not infer and persist every private field that happened to change.
Arbitrary registration delegates, captured closures and custom activator state cannot be turned into portable executable instructions. Unsupported registration shapes are rejected rather than guessed. Keep special runtime configuration in an application-owned manifest or construction step and document how the reader obtains it. Do not promise that a file contains everything merely because one part is self-describing.
Frame and Validate the Container
A practical container needs framing around the two records. For example, an application can reserve separate clustered streams for metadata and payload, or define bounded length-prefixed sections. It must also identify its own format version and decide what happens when the required type assembly is unavailable. Those policies belong to the application, not to an undocumented side effect of the serializer factory.
This mechanism is particularly useful when building reusable storage containers or understanding self-describing ObjectSpaces. Read the factory codec guide for its supported registration table and limitations, and inspect the implementation . The Sphere10 Framework overview shows how these layers combine without requiring a database server.
Download the Example
Download the complete NuGet sample project. The archive contains the project, its model files and run instructions. Keep the pinned package version when reproducing the example.
Continue the Series
How to Build a Self-Describing Object Store
How to Serialize an Object Graph Without Losing Shared References
How to Store Many Independent Streams Inside One File