Skip to content

Commit

Permalink
Fix serializing objects with custom child types using DataObject/Clip…
Browse files Browse the repository at this point in the history
…board
  • Loading branch information
cwensley committed Aug 1, 2023
1 parent 02ad389 commit 4d6a4da
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
33 changes: 31 additions & 2 deletions src/Eto/Forms/ObjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal static byte[] Serialize(object value, Type baseType)

using (var ms = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(ObjectData), new [] { baseType });
var serializer = new DataContractSerializer(typeof(ObjectData), GetKnownTypes(baseType));
serializer.WriteObject(ms, data);

// for debugging
Expand All @@ -35,6 +35,34 @@ internal static byte[] Serialize(object value, Type baseType)
return ms.ToArray();
}
}

static IEnumerable<Type> GetKnownTypes(Type baseType)
{
yield return baseType;

// DataContracts must specify their types explicitly using the KnownTypeAttribute
var isDataContract = baseType.GetCustomAttribute<DataContractAttribute>() != null;
if (isDataContract)
yield break;

var knownTypes = new HashSet<Type>();

foreach (var field in FormatterServices.GetSerializableMembers(baseType))
{
var type = field switch
{
PropertyInfo pi => pi.PropertyType,
FieldInfo fi => fi.FieldType,
_ => null
};
if (!knownTypes.Contains(type))
{
yield return type;
knownTypes.Add(type);
}
}
}


internal static object Deserialize(Stream stream, Type objectType)
{
Expand Down Expand Up @@ -73,7 +101,8 @@ internal static object Deserialize(Stream stream, Type objectType)
{
// read again, but with known type populated
stream.Position = 0;
var serializer = new DataContractSerializer(typeof(ObjectData), new[] { objectType });

var serializer = new DataContractSerializer(typeof(ObjectData), GetKnownTypes(objectType));
var data = serializer.ReadObject(stream) as ObjectData;

ms?.Dispose();
Expand Down
10 changes: 10 additions & 0 deletions test/Eto.Test/UnitTests/Forms/ClipboardTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,35 @@ public class SerializableObject : ISerializable
{

public string SomeValue { get; set; }
public ChildObject ChildObject { get; set; } = new ChildObject();
public SerializableObject()
{
}

public SerializableObject(SerializationInfo info, StreamingContext context)
{
SomeValue = info.GetString("SomeValue");
ChildObject = info.GetValue("Child", typeof(ChildObject)) as ChildObject;
}

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("SomeValue", SomeValue);
info.AddValue("Child", ChildObject);
}
}

[Serializable]
public class SomeOtherObject
{
public string SomeValue { get; set; }

public ChildObject ChildObject { get; set; } = new ChildObject();
}

public class ChildObject
{
public bool SomeProperty { get; set; } = new Random().Next() % 2 == 0;
}

static byte[] SampleByteData => new byte[] { 10, 20, 30 };
Expand Down

0 comments on commit 4d6a4da

Please sign in to comment.