You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Registering polymorphic objects directly does not work correctly when trying to serialize those objects from other objects.
Here is an example:
public class Wrapper
{
public Letters field { get; set; }
}
public interface Letters
{
}
public class A : Letters
{
public string ItemA { get; set; }
}
public class B : Letters
{
public string ItemB { get; set; }
}
public abstract class SubType
{
}
public class SubTypeA : SubType
{
public string ItemD { get; set; }
}
public class SubTypeB : SubType
{
public string ItemE { get; set; }
}
As shown, the polymorphic 'Letters' is within the class 'Wrapper'.
Now trying to register these to the SerializationContext...
SerializationContext context = new SerializationContext();
context.GetSerializer<SubType>(
PolymorphismSchema.ForPolymorphicObject(
typeof(SubType),
new Dictionary<string, Type>
{
{"A", typeof(SubTypeA)},
{"B", typeof(SubTypeB)}
}));
context.GetSerializer<IType>(
PolymorphismSchema.ForPolymorphicObject(
typeof(IType),
new Dictionary<string, Type>
{
{"A", typeof(TypeA)},
{"B", typeof(TypeB)}
}));
MessagePackSerializer<Wrapper> serializerWrapper = context.GetSerializer<Wrapper>();
// The above line breaks due to 'System.NotSupportedException: 'This operation is not supported because 'IType' cannot be instantiated.'
`
This shouldn't happen, because the context should internally register the serializers it gets.
From what I've dug up, the problem is that the serializer that context.GetSerializer creates is null for polymorphic types.
In SerializationContext.cs line 692: serializer = this.OnResolveSerializer<T>( schema ) ?? MessagePackSerializer.CreateInternal<T>( this, schema );
MessagePackSerialier.CreateInternal is called.
And then in MessagePackSerializer.Factories.cs lines 247-251:
if ( concreteType == null )
{
// return null for polymoirphic provider.
return null;
}
The returned serializer is null, and so the provider is given a null default serializer at SerializationContext.cs line 724: provider = new PolymorphicSerializerProvider<T>( serializer );
And then when SerializationContext.cs line 741 is reached:
this._serializers.Register(
typeof( T ),
provider,
nullableType,
nullableSerializerProvider,
SerializerRegistrationOptions.WithNullable
)
A faulty serializer is registered.
But, context.GetSerializer returns the correct serializer because SerializationContext.cs line 760 return this._serializers.Get<T>( this, providerParameter );
will use the schema to create the correct serializer.
Registering polymorphic objects directly does not work correctly when trying to serialize those objects from other objects.
Here is an example:
As shown, the polymorphic 'Letters' is within the class 'Wrapper'.
Now trying to register these to the SerializationContext...
`
This shouldn't happen, because the context should internally register the serializers it gets.
From what I've dug up, the problem is that the serializer that context.GetSerializer creates is null for polymorphic types.
In SerializationContext.cs line 692:
serializer = this.OnResolveSerializer<T>( schema ) ?? MessagePackSerializer.CreateInternal<T>( this, schema );
MessagePackSerialier.CreateInternal is called.
And then in MessagePackSerializer.Factories.cs lines 247-251:
The returned serializer is null, and so the provider is given a null default serializer at SerializationContext.cs line 724:
provider = new PolymorphicSerializerProvider<T>( serializer );
And then when SerializationContext.cs line 741 is reached:
A faulty serializer is registered.
But, context.GetSerializer returns the correct serializer because SerializationContext.cs line 760
return this._serializers.Get<T>( this, providerParameter );
will use the schema to create the correct serializer.
A work around for this issue is:
Where the correctly returned serializer is then re-registered with the context.
But, I propose solving this issue by changing the MessagePackSerializer.Factories.cs lines 247-251 to this:
This is what PolymorphicSerializerProvider.cs does anyway at the end of context.GetSerializer.
The text was updated successfully, but these errors were encountered: