Strange Deserialization from Disk Transport

I came across a strange phenomenon - serialization and deserialization of a Base to disk seems to lose its “real” type, even though .GetType() is correct?

See attached .dib file, which can be run directly in VSCode.


TestTrasnportDeserialization.dib (3.4 KB)

Steps:

  1. Retrieve a Speckle Object (in this case, a Brep) from a Speckle Server - call it “apiBrep”
  2. Serialize and then, deserialize it to disk, using a DiskTransport - call it “diskBrep”
  3. Verify result of .GetType() on each object. It should return “Objects.Geometry.Brep” for both.
  4. Access properties of each type:
  • Dictionary-style properties (e.g. ["Faces"]) return correctly
  • Dot-notation-style properties return the following error:
Error: (1,10): error CS1061: 'Base' does not contain a definition for 'Faces' and no accessible extension method 'Faces' accepting a first argument of type 'Base' could be found (are you missing a using directive or an assembly reference?)

This is a problem when using the disk-deserialized object in methods, as the compiler complains that the object is actually just a Base, (and not the “complete” Speckle Object .GetType() thinks it is); and so we recieve the following error:

Error: (1,14): error CS1503: Argument 1: cannot convert from 'Speckle.Core.Models.Base' to 'Objects.Geometry.Brep'

Any ideas?

Operations.Receive() will always return a Base object.

You have two options from there. Cast diskBrep to Objects.Geometry.Brep and directly address the faces properties or as Base objects are all DynamicBase objects use dynamic indexing to extract the properties you want. Choose your poison.

2 Likes

Thanks @jonathon. That is the solution.

However, it is not clear that Operations.Receive() returns a Base, for two reasons:

  1. Calling .GetType() immediately on the returned object from Operations.Receive() actually states that the object is already cast? (ie, in this case, Objects.Geometry.Brep, rather than Base)
  2. The documentation around deserialization is a bit vague. BaseObjectDeserializerV2.Deserialize() states it returns “a Base typed object deserialized from the ‘rootObjectJson’”, however from pt 1 above, to a user it looks like the deserialization has also cast it to its original type (and needs no further casting…)

Could documentation (or perhaps, automatic casting of received objects) be added?

1 Like

You are right; our documentation in many places can always be improved, this is one of them, I’ll add it to the list :spockle_smirk: