Open LeroyK opened 5 years ago
I don’t think these types should be made public as-is. These types weren’t designed to be part of a public, stable interface. Their API isn't as intentionally designed as public Bond APIs. They are tightly coupled to each other & other components. Since these are so fundamental to the nuts & bolts implementation of serialization/deserialization, I'd like to leave the flexibility to make breaking interface changes in these types as we maintain and improve Bond.
It would be useful to have more information about your custom serializer to understand how you're using the existing APIs and what the gap in them is. Perhaps there is a smaller extension point? Perhaps this is indicative of the need for a new family of APIs? For example, I've been mulling over what a C# API like the C++ Transform/Apply API would look like.
By default Bond uses its default implementation in its compiled expressions for deferred serialize/deserialize (e.g. to serialize bond fields). I want to be able to wrap these expressions with my custom logic to support polymorphism.
There are a couple of options I can think of to support this:
public delegate Expression<Action<object, W>> DeferredSerialize(Type type, Expression<Action<object, W>> deferredSerialize);
public delegate Expression<Func<R, object>> DeferredDeserialize(Type type, Expression<Func<R, object>> deferredDeserialize);
SerializerHelper
& TwoPassSerializerHelper<FPW>
take ObjectParser
in their constructors (here and here) instead of IParser. This actually might be a bug and I think the parameter should be of type IParser
. I haven't explored this further because I was never able to use a custom parser because of this.Thanks for the details. Can you also talk about the custom logic to support polymorphism? That will help get a fuller picture of what your thinking about.
Sure, currently I basically do the following:
Bond.IBonded
in each type that needs polymorphism.Bond.Expressions.PayloadBondedFactory
to create a custom PolyBondedVoid<R>
Bond.Factory
to call my custom deserializer.DiscriminatorStruct<TDiscriminatorEnum>
for each Bond.Id
(0..65535) that's being used.I wanted to use Bond.Expressions.ObjectBondedFactory
as well, but it's bugged.
To make it as fast as possible, my code uses reflection to compile expression trees.
This small example will give you an idea what my model looks like:
[Bond.Schema]
public class Owner
{
[Bond.Id(0)]
[Bond.Type(typeof(List<bonded<Pet>>))]
public List<Pet> Pets { get; set; }
}
[Bond.Schema]
[Discriminator(Discriminator.Pet)]
public class Pet : Bond.IBonded
{
public enum Discriminator : byte
{
Pet = 0,
Dog = 1,
Parrot = 2
}
[Bond.Id(0)]
public Discriminator TypeDiscriminator { get; set; }
[Bond.Id(1)]
public long Id { get; set; }
void Bond.IBonded.Serialize<W>(W writer) => PolyBond.Serialize(this, writer);
U Bond.IBonded.Deserialize<U>() => default;
Bond.IBonded<U> Bond.IBonded.Convert<U>() => null;
}
[Bond.Schema]
[Discriminator(Discriminator.Dog)]
public class Dog : Pet
{
[Bond.Id(0)]
public bool Barks { get; set; }
}
[Bond.Schema]
[Discriminator(Discriminator.Parrot)]
public class Parrot : Pet
{
[Bond.Id(0)]
public bool Speaks { get; set; }
}
I have created a custom polymorphic bond serializer and deserializer that uses SerializerTransform, DeserializerTransform and SerializerGeneratorFactory through reflection. This allows it to automatically use my custom serializer for all nested types, which would otherwise not be possible.
Even though this works fine via reflection, I would prefer these types to be available at compile time. Could we make these types public? I'd be happy to submit a PR for it.