Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help request - using different (derived-)types for serialize/deserialize (IMessagePackFormatter<Tser, Tdes>)? #1778

Open
GunSharp opened this issue Feb 23, 2024 · 2 comments

Comments

@GunSharp
Copy link

Hi All,

I'm seeking assistance for a challenge I'm facing with an existing C# library that utilizes Microsoft binary serialization for a large number of classes. I'm exploring MessagePack as an alternative for serialization.

In this library, certain classes have a unique behavior during serialization and deserialization. During serialization, only an identifier is written into the stream, and during deserialization, this identifier is used to retrieve the corresponding object from a global dictionary.

However, I'm encountering difficulties when the deserialized object is of a different type than the serialized object. Let me illustrate this with a simplified class model:

class Base { readonly string Id = "MyId"; }
class A : Base { }
class B : Base { }

(The goal is to substitute all references to instances of class A with references to instances of class B during deserialization. )

During serialization of class A , the identifier of the base class ("MyId") is written into the stream. To substitute class A with class B, an instance of class B is registered in the global dictionary with the identifier "MyId". Then, during deserialization from the stream, the deserialized object is retrieved from the global dictionary using the key "MyId" and is returned as deserialized object.

Currently, I'm using a CustomResolver based on SampleCustomResolver, where I've implemented logic to read and write the identifier. However, I'm struggling to achieve the desired behavior because IMessagePackFormatter requires the type for serialization and deserialization to be the same. Additionally, I'm facing challenges in making this work for the base class.

So maybe something like IMessagePackFormatter<A, B> where A : Base and B : Base

I'm also using TypelessContractlessStandardResolver to ensure compatibility with the old library and make as little changes as possible.

I would appreciate any tips or guidance on how to address this issue.

Thank you in advance for your assistance.

@AArnott
Copy link
Collaborator

AArnott commented Mar 4, 2024

I think you'll have to implement your formatter in terms of Base instead of A or B, since as you've noticed, there's no way an A formatter will be allowed to return a B. That will require that whatever node is pointing to your A/B objects actually declares the type to be Base instead of A simply for CLR type assignability rules.

@GunSharp
Copy link
Author

Thank you mr AArnott for your reply.

I have tried to implement a formatter in terms of Base however I did not manage to make it work (my node indeed points to the base type). Somehow it doesn't seem to 'catch' my formatter when I use the formatterMap as shown in the examples.

    static readonly Dictionary<Type, object> formatterMap = new Dictionary<Type, object>()
    {
	    {typeof(Base), new MyBaseFormatter ()},
        }

However, next week, I'll give it a try again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants