Potential Bug with IntermediateSerializer

Hi

Two potential bugs with IntermediateSerializer. Im basing this off Shawn Hargreaves sumary of the XNA implementation here

  1. Get and Set not public
    In XNA, the following property would not be serialized or de-serialized because only the get is public, the set is not implemented.

public override Type ObjectSpawnClass { get { return typeof(RpgLibrary.SomeClass); } }

With the 3.6 install, Intermediate Serializer throws a "Exception thrown: 'System.NotImplementedException' in MonoGame.Framework.Content.Pipeline.dll" with “Unhandled primitive type System.IntPtr!"

Adding a [ContentSerializerIgnore] is a simple workaround.

  1. [ContentSerializer(Optional = true)] not respected
    The attribute [ContentSerializer(Optional = true)] applied to a object property does not appear to be respected when serializing a class where that object is null. Instead it will attempt to serialize the null object and throw a confusing “System.Reflection.TargetException” exception. XNA did not work this way, that property was skipped during serialization.

This was a very handy feature. When adding a new object to a class, its not viable to manually fixup 100’s of data files. Rather, I would add that class, flag it as optional then fixup the data files as time allowed.

Thanks!

3 Likes

Thanks for reporting these. Would you mind opening 2 issues for these on the GitHub page?

Hi

I pulled down the source, built the assemblies and debugged #2 above. My description in the OP was incorrect.

I have a fairly complicated XML structure within my game, so I’m not 100% sure on the repro steps, however I believe that the following is the minimum needed to cause a TargetException in PropertyInfo.GetValue:

  • XML object A contains an embedded object B to serialize
  • That object B contains an object C.
  • Object C is NULL.

In this case, we recurse calling ReflectiveSerializer::ScanChildren() until we get to object C.
ReflectiveSeralizer::ScanChildren() has no NULL guard on the passed in object value.
We then end up calling the lambda var elementValue = info.Getter(value) for the first property in C’s class;
value is null, since C was null, which triggers a TargetException() in PropertyInfo.GetValue().
This matches MSDNs reason for that exception: “The object does not match the target type, or a property is an instance property but obj is null” - the object is NULL.

I added a NULL guard to ReflectiveSerializer::ScanChildren() and everyting “appears” to work. I can load/save my entire game structure now, and a diff shows no differences in the output with/without this change.

I dont know the IntermediateSerializer code well enough to know if this is a safe fix. Could one of the experts let me know?

Additionally - after stepping through the Mono source (and having years of XNA experience and 20 years of professional game dev experience) - I have the utmost respect for the MonoGame team. The amount of work to port XNA is staggering. I have to ask - did MS give you any source for XNA, or did you port via the online specs only?

–Phantasie