Prowl.Echo exposes five interfaces that let you hook into and extend different layers of the serialization pipeline.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ProwlEngine/Prowl.Echo/llms.txt
Use this file to discover all available pages before exploring further.
ISerializable and ISerializationCallbackReceiver operate at the object level, giving you fine-grained control over how individual types are read and written. ISerializationFormat sits at the pipeline level, letting you register handlers for new categories of types. IFileFormat governs how EchoObject trees are persisted to bytes, strings, or files. IEchoLogger provides an optional structured logging hook for diagnostics. Together, these interfaces cover every extension point the library offers.
ISerializable
ISerializable when you need complete control over how a type is converted to and from an EchoObject. The most common reason to implement it manually is to handle types whose internal state cannot be expressed through simple field mapping — for example, types backed by a native handle, types that derive their serialized form from computed properties, or types with complex versioning logic.
[GenerateSerializer] auto-generates a correct ISerializable implementation for partial classes and structs at compile time. Only implement this interface manually when the generated code does not satisfy your requirements.Methods
The output compound container. Add named child
EchoObject entries to it to record your type’s state. The compound is pre-created for you; you do not need to call EchoObject.NewCompound() yourself.The active serialization context. Pass this through to
Serializer.Serialize / Serializer.Deserialize when you recurse into nested types so that settings such as TypeMode are propagated correctly.Example
ISerializationCallbackReceiver
ISerializationCallbackReceiver lets a type participate in the serialization lifecycle without taking over the entire read/write process. This is useful when most fields serialize normally but you need to prepare or restore transient, derived, or cached state around those operations.
Methods
Called immediately before Echo serializes the object. Use this to populate any fields that must be written but are ordinarily derived from other state — for example, converting a runtime
Dictionary into a serializable list of key–value pairs.Called immediately after Echo finishes writing deserialized values into the object’s fields. Use this to rebuild caches, re-establish object references, or validate the deserialized state.
Example — rebuilding a lookup dictionary after deserialization
ISerializationFormat
ISerializationFormat is the extension point for teaching Echo how to serialize an entirely new category of types. Registered formats are consulted in registration order before the built-in formats, except for AnyObjectFormat, which is always evaluated last as the final fallback.
Register a custom format with:
Methods
Return
true for every Type this format should handle. Echo calls CanHandle on each registered format in order and uses the first one that returns true. Keep the check fast — it is called on every unique type the first time that type is serialized.Convert
value (which is guaranteed to be non-null and of a type for which CanHandle returned true) into an EchoObject. Return a Compound, List, or primitive EchoObject as appropriate.Convert an
EchoObject back into an instance of targetType. Return null only if targetType is a reference type and the serialized value was null.Example — custom format for a Color struct
IFileFormat
IFileFormat defines how an EchoObject tree is encoded into bytes and decoded back again. The two core methods work with Stream, keeping the interface transport-agnostic. A suite of extension methods — defined in the static class FileFormatExtensions — wraps these core methods for the common cases of strings, byte arrays, and file paths.
Core methods
Write the complete
EchoObject tree rooted at tag to stream. The stream is not closed or flushed by the implementation; callers are responsible for lifetime management.Read bytes from
stream and reconstruct the EchoObject tree. Throws InvalidDataException if the stream does not contain valid data for this format.Extension methods (FileFormatExtensions)
These extension methods are available on anyIFileFormat implementation, including custom ones you write yourself.
| Method | Returns | Description |
|---|---|---|
WriteToString(EchoObject tag) | string | Serialize to a UTF-8 string. Best suited for text-based formats. |
ReadFromString(string input) | EchoObject | Deserialize from a UTF-8 string. |
WriteToBytes(EchoObject tag) | byte[] | Serialize to a byte array. Works for both text and binary formats. |
ReadFromBytes(byte[] data) | EchoObject | Deserialize from a byte array. |
WriteToFile(EchoObject tag, string path) | void | Serialize and write directly to a file path. |
ReadFromFile(string path) | EchoObject | Read and deserialize from a file path. |
Example
IEchoLogger
IEchoLogger is a thin structured-logging abstraction that Echo uses internally to report diagnostic information, type resolution warnings, and serialization errors. Implement it to route Echo’s log output into your application’s existing logging infrastructure.
The default logger is NullEchoLogger, which silently discards all messages. No log output is produced unless you assign a custom logger.
Methods
Low-verbosity trace messages. Useful during development to understand how types are resolved and which formats are selected.
General informational messages such as cache-clear notifications.
Non-fatal issues such as unrecognized type names or fields skipped during deserialization.
Errors encountered during serialization or deserialization. The optional
exception parameter carries the underlying exception when one is available.Assigning a custom logger
Serializer.Logger is a static property on Prowl.Echo.Serializer. The default value is new NullEchoLogger(), which is a no-op implementation bundled in the Echo.Logging namespace.