ModernRonin / MessagePack.Attributeless

Use MessagePack without attributes, even for polymorphy, yet in a type-safe and space-efficient manner

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: Could it be made to support ISerializable?

MooVC opened this issue · comments

Hi - Amazing library, thank you for the amazing contribution.

I was very excited when I found it, as I've been struggling to find a suitable replacement for BinaryFormatter for some time. At present I am using typeless, but as you have pointed out, it is much slower and the destillates are huge in comparison to the default/contractless approaches. My projects typically have a set of base classes in a core library that other libraries implement to address business specific challenges. The base classes are marked as [Serializable] and always implement ISerializable. I liked this approach, as it granted a lot of flexibility WRT serialization implementation, but I've noticed most 'modern' serializers tend to ignore ISerializable. In most cases, the classes tend to be "immutable" from the outside i.e. properties are marked as get only or have a private set. The idea being that state is managed through a specific channel (e.g. via domain events). The limitations of Attributeless renders its unsuitable in its current form, but I am wondering if extensibility points exist that would allow for support for an ISerializable based approach?

Appreciate any insights/suggestions you can offer.

In principle, you need just an implementation of IMessagePackFormatter<ISerializable> that will look something like:

public sealed class SerializableMessagePackFormatter : IMessagePackFormatter<ISerializable>
    {
        public void Serialize(ref MessagePackWriter writer, ISerializable value, MessagePackSerializerOptions options)
        {
            var info= new SerializationInfo(...); // that's actually a bit more complicated, but you get the idea
            value.GetObjectData(info, null); // assuming you don't do anything with the context in your implementations
            // now info is populated
           foreach (var entry in info)
           {
               var type= entry.ObjectType;
               var value= entry.Value;
               MessagePackSerializer.Serialize(type, ref writer, value, options);
           }
        }
        public ISerializable Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) 
        { 
          // BIG CAVEAT, see text below
        }
    }

and then you'd register that implementation with MessagePack.

The BIG CAVEAT:
In a short check through some of the existing IFormatter implementations or their decompiled sources I did not find any way to get a SerializationInfo from a type, instead of an instance. But this you would need for .Deserialize(), otherwise you won't know which properties to expect.

Maybe I just didn't find it, then the above is the way to go. But if there really is nothing like it, then the only thing I can think of would be to create an instance of the type and get it from there - you'd be interested in Name and ObjectType only.
However, this might be
a) costly, depending on your types
b) not work at all if your implementations of .GetObjectData() add properties conditionally on some state

Maybe some of all this helps you,
Cheers,
MR

That's a big help; Thank you, it's must appreciated.

As most of the solutions in question tend to be long running background processes, a high upfront cost that yields faster execution times on persistence and data transmission would be a justifiable trade-off. Some implementations do possess conditional selection on serialization/deserialization, but this was mainly applied as an optimization that had questionable benefits to begin with (it's basically a do not serialize empty/null/default condition). I'll try to apply as you suggested and will let you know how it goes. Again, much appreciated.