Closed inethui closed 2 years ago
One thing worth to mention, if I remove the relationship between "IEntityNameAndId" and "NameAndIdBase", then the serialization of "Property" works. Don't know why. Any idea?
This is the unit test code to replicate the issue:
using AqlaSerializer;
using System;
using System.Diagnostics;
using System.IO;
using Xunit;
public class UnitTest5
{
private void SetupModel()
{
var metaType2 = AqlaSerializer.Meta.RuntimeTypeModel.Default.Add(typeof(Property), false);
metaType2.DefaultFormat = AqlaSerializer.ValueFormat.Reference;
metaType2.UseConstructor = false;
metaType2.IgnoreListHandling = true;
var metaType3 = AqlaSerializer.Meta.RuntimeTypeModel.Default.Add(typeof(IEntityNameAndId), false);
metaType3.DefaultFormat = AqlaSerializer.ValueFormat.Reference;
metaType3.UseConstructor = false;
metaType3.IgnoreListHandling = true;
var metaType4 = AqlaSerializer.Meta.RuntimeTypeModel.Default.Add(typeof(INameAndId), false);
metaType4.DefaultFormat = AqlaSerializer.ValueFormat.Reference;
metaType4.UseConstructor = false;
metaType4.IgnoreListHandling = true;
AqlaSerializer.Meta.MetaType metaType5 = AqlaSerializer.Meta.RuntimeTypeModel.Default[typeof(IEntityNameAndId)];
metaType5.AddSubType(1, typeof(INameAndId));
AqlaSerializer.Meta.MetaType metaType6 = AqlaSerializer.Meta.RuntimeTypeModel.Default[typeof(Property)];
var metaField1 = metaType6.AddField(1, "_owner");
metaField1.SetSettings(x => { x.V.Format = AqlaSerializer.ValueFormat.Reference; });
metaField1.SetSettings(x => x.V.WriteAsDynamicType = true, 0);
var metaType7 = AqlaSerializer.Meta.RuntimeTypeModel.Default.Add(typeof(NameAndIdBase), false);
metaType7.DefaultFormat = AqlaSerializer.ValueFormat.Reference;
metaType7.UseConstructor = false;
metaType7.IgnoreListHandling = true;
AqlaSerializer.Meta.MetaType metaType8 = AqlaSerializer.Meta.RuntimeTypeModel.Default[typeof(NameAndIdBase)];
var metaField2 = metaType8.AddField(1, "_id");
metaField2.SetSettings(x => { x.V.Format = AqlaSerializer.ValueFormat.Compact; });
var metaField3 = metaType8.AddField(2, "_name");
metaField3.SetSettings(x => { x.V.Format = AqlaSerializer.ValueFormat.Compact; });
AqlaSerializer.Meta.MetaType metaType10 = AqlaSerializer.Meta.RuntimeTypeModel.Default[typeof(IEntityNameAndId)];
metaType10.AddSubType(2, typeof(NameAndIdBase));
var metaType11 = AqlaSerializer.Meta.RuntimeTypeModel.Default.Add(typeof(NameAndId), false);
metaType11.DefaultFormat = AqlaSerializer.ValueFormat.Reference;
metaType11.UseConstructor = false;
metaType11.IgnoreListHandling = true;
AqlaSerializer.Meta.MetaType metaType12 = AqlaSerializer.Meta.RuntimeTypeModel.Default[typeof(NameAndIdBase)];
metaType12.AddSubType(3, typeof(NameAndId));
}
[Fact]
public void TestSerialization()
{
SetupModel();
var property = new Property();
property.Owner = new NameAndId(101, "test");
var stream = new MemoryStream();
try
{
Serializer.Serialize(stream, property);
}
catch (Exception e)
{
Debug.WriteLine($"Failed to serialize property: {e.Message}");
throw;
}
}
}
public class Property
{
private INameAndId _owner;
public INameAndId Owner { get => _owner; set => _owner = value; }
}
public sealed class NameAndId : NameAndIdBase, INameAndId
{
public NameAndId(int id, string name)
: base(id, name)
{
}
}
public class NameAndIdBase : IEntityNameAndId
{
private readonly string _name = string.Empty;
private readonly int _id;
public NameAndIdBase(int id, string name)
{
_id = id;
_name = name;
}
public int Id => _id;
public string Name => _name;
}
public interface INameAndId : IEntityNameAndId
{
}
public interface IEntityNameAndId
{
int Id { get; }
string Name { get; }
}
If we remove the following two lines from the "SetupModel" method, the test passes. I don't know why.
AqlaSerializer.Meta.MetaType metaType10 = AqlaSerializer.Meta.RuntimeTypeModel.Default[typeof(IEntityNameAndId)];
metaType10.AddSubType(2, typeof(NameAndIdBase));
Found a workaround on our side.
I have classes with the relationships depicted in the attached class diagram:
How to setup Aqla for those classes? It seems that the straightforward setup for each relationship doesn't work. Our code assigns an instance of class "NameAndId" to "Property._owner", which is type "INameAndId". When we try to serialize "Property" object, we get exception saying unexpected sub-type "NameAndId" for "Property._owner". "Property._owner" is defined as a dynamic type.
Any suggestions? Thanks