Closed warriordog closed 1 year ago
if this option is taken, it will become a prerequisite for the other work in the project.
I'm going to prototype this in the linked branch. A bit of unimportant tracking:
Features to re-implement later:
ASType.Types
Idea - what if TypeMap
becomes the object root, instead of ASType? It would become the central node on the type graph and would make a convenient type for "any valid ActivityPub type". We should probably rename it then.
The alternative is to implement a common ASBase
or something that contains no properties (since it wont be managed by the graph) but does contain the TypeMap
pointer.
Found a way to make the type graph more ergonomic and consistent with C# principles. Put simply, we implement both a type graph and an inheritance chain. The inheritance chain becomes the normal public API, and should be drop-in compatible with the existing type model. However, those types will contain no data at all. Instead, they each wrap an entity class, which is a singleton node from the type graph. The entity classes contain all the data, along with serialization logic. Thus, multiple objects with common base types can exist, while the shared base types still act like singletons.
Here's an example diagram (sorry, its hard to read):
JSON / JSON-LD conversion will now consist of two steps:
ASTypeConverter
, but shouldn't be too hard. I believe we can create a new TypeMap
then construct each entity from the same JsonElement
. Since the entity constructor automatically attaches to the TypeMap, everything will fit into place as we go.System.Text.Json
, so anything after that will require explicit calls from upstream code. The type constructors are designed to accept and pass down a TypeMap
instance, and each intermediate constructor will extract the appropriate entity.Overall, this seems to be a fully viable solution to the problem!
Pros:
Cons:
ASType
and ASBase
Neutrals:
ASBaseConverter
(lots of work, but could help with #65)JsonPropertyInfo<T>
. That opens up the possibility of using Static Virtual Interface Members to avoid some reflection.
This would be a drastic and extreme change that impacts the entire project, but there are valid reasons to explore is.
This change, if we decide to make it, will drop the object-oriented structure of the ActivityStreams types in favor of a more compositional structure. Types would contain only their unique properties and a link to their own "base" type and the root ASType / ASObject instance(s). We would, effectively, create a small graph out of each "object". The "root" (ASType, most likely) will additionally have functions to find and access any "leaf" in the graph. This allows type-safe navigation from any object through its base type hierarchy, and also safe navigation from the root to any standard or extension type associated with the object.
For this to work we will still need TypeMap for extension support, but it can be attached to ASType and continue to work as-designed. In fact, the implementation of
TypeMap
will be much simpler with this change.Constructing an object without JSON: