Chronicler.Core
0.1.0
dotnet add package Chronicler.Core --version 0.1.0
NuGet\Install-Package Chronicler.Core -Version 0.1.0
<PackageReference Include="Chronicler.Core" Version="0.1.0" />
<PackageVersion Include="Chronicler.Core" Version="0.1.0" />
<PackageReference Include="Chronicler.Core" />
paket add Chronicler.Core --version 0.1.0
#r "nuget: Chronicler.Core, 0.1.0"
#:package Chronicler.Core@0.1.0
#addin nuget:?package=Chronicler.Core&version=0.1.0
#tool nuget:?package=Chronicler.Core&version=0.1.0
Chronicler
![]()
Chronicler is a deterministic, transport-neutral serialization library for lockstep simulation, snapshot/restore workflows, and runtime state transfer into existing object graphs.
Unlike attribute-only serializers, Chronicler makes each type explicitly own its serialized shape through RecordData(IChronicler chronicler).
Key Features
- Deterministic record passes for systems that care about stable, explicit state flow.
- Transport-neutral core API with built-in JSON and MemoryPack support.
- Type-owned schemas through
IRecordable, without requiring serializer attributes on most domain types. - Canonical default handling so omitted entries load into known values instead of ambient runtime state.
- Deep graph support for nested owned objects and structs already present in the runtime shell.
- Stable link support for runtime-owned or external references through a session-scoped registry.
- Designed for lockstep and restore flows where the host owns construction and Chronicler owns state transfer.
Installation
NuGet
dotnet add package Chronicler.Core
Source
git clone https://github.com/mrdav30/Chronicler.git
Then reference src/Chronicler/Chronicler.csproj directly or build the package locally.
API Overview
Chronicler is built around three primary recording lanes:
RecordValuesfor leaf values such as primitives, enums, and small deterministic structs.RecordDeep/RecordDeepStruct/RecordNullableDeepfor owned nested recordable state.RecordLinksfor stable references to runtime-owned or external objects.
Core abstractions:
IRecordableIChroniclerChronicleContextChronicleLinkRegistry
Built-in transports:
JsonRecordSerializerMemoryPackRecordSerializer
Important design note:
- Chronicler loads into an existing initialized runtime shell. It does not construct arbitrary object graphs from transport data alone.
Quick Start
Define a recordable type
using Chronicler;
public sealed class PlayerSnapshot : IRecordable
{
public int Health = 100;
public int Mana = 50;
public WeaponState Weapon = new();
public void RecordData(IChronicler chronicler)
{
RecordValues.Look(chronicler, ref Health, "health", 100);
RecordValues.Look(chronicler, ref Mana, "mana", 50);
RecordDeep.Look(chronicler, ref Weapon, "weapon");
}
}
public sealed class WeaponState : IRecordable
{
public int Ammo = 30;
public void RecordData(IChronicler chronicler)
{
RecordValues.Look(chronicler, ref Ammo, "ammo", 30);
}
}
Serialize and populate with JSON
PlayerSnapshot source = new();
string json = JsonRecordSerializer.Serialize(source, writeIndented: true);
PlayerSnapshot target = new()
{
Weapon = new WeaponState()
};
JsonRecordSerializer.Populate(target, json);
Serialize and populate with MemoryPack
PlayerSnapshot source = new();
byte[] data = MemoryPackRecordSerializer.Serialize(source);
PlayerSnapshot target = new()
{
Weapon = new WeaponState()
};
MemoryPackRecordSerializer.Populate(target, data);
Stable Links
Use RecordLinks when a field points to a runtime-owned or external object that should not be serialized inline.
public sealed class ActorState : IRecordable
{
public RuntimeEntity? Target;
public void RecordData(IChronicler chronicler)
{
RuntimeEntity? target = Target;
RecordLinks.Look(chronicler, ref target, "target");
if (chronicler.Mode == SerializationMode.Loading)
Target = target;
}
}
Resolve those links through the session context:
ChronicleContext context = new();
context.Links.RegisterInstance("player-42", runtimeEntity);
For cases where the target object is only available after the rest of the graph loads, use deferred link resolution with RecordLinks.LookDeferred(...).
Design Rules
- Pass canonical declared defaults to
RecordValues.Look(...). - Use
RecordDeepfor owned nested objects that already exist in the runtime shell. - Use
RecordDeepStructfor non-nullable nested recordable structs. - Use
RecordNullableDeepfor optional nested recordable structs. - Use
RecordLinksfor runtime-owned or external references. - Keep object construction and framework bootstrap outside the base Chronicler contract.
Development
Build the solution:
dotnet build Chronicler.sln -c Release
Run the unit tests:
dotnet test tests/Chronicler.Tests/Chronicler.Tests.csproj -c Release --no-build
Run tests with coverage:
dotnet test tests/Chronicler.Tests/Chronicler.Tests.csproj -c Release --collect:"XPlat Code Coverage" --settings coverlet.runsettings
Compatibility
netstandard2.1net8.0- Windows, Linux, and macOS
JSON support is provided through System.Text.Json, and binary transport support is provided through MemoryPack.
Contributing
We welcome contributions. Please see CONTRIBUTING for contribution guidance and project expectations.
Contributors
- mrdav30 - Lead Developer
- Contributions are welcome through issues and pull requests.
Community & Support
For bug reports or feature requests, please open an issue in this repository.
For general discussion and support, join the official Discord community:
License
This project is licensed under the MIT License.
See the following files for details:
LICENSE- standard MIT licenseNOTICE- additional terms regarding project branding and redistributionCOPYRIGHT- authorship information
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- MemoryPack (>= 1.21.4)
- SwiftCollections (>= 3.0.0)
- System.Text.Json (>= 10.0.5)
-
net8.0
- MemoryPack (>= 1.21.4)
- SwiftCollections (>= 3.0.0)
- System.Text.Json (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.