views:

119

answers:

2

I have a generic collection of shapes that I need to pass through WCF to store in a database for future/shared use. Unfortunately, the System.Windows.Shapes are all sealed, so I can't inherit them and make a serializable copy of them. I "could" write my own custom set of serializable shapes, as I have written 3 custom shapes for my app anyway, but I'd like to not have to if possible.

I am fully aware that I could use a XAMLReader and XAMLWriter to take them off the screen, and put them back, but this isn't quite good enough, as the size of the Grid containing the shapes isn't always the same, and I need the shapes to be repositioned accordingly. The shapes are being used as an overlay on another image, and it is VERY important that the shapes remain in the same place over the background image.

Any ideas or help would be appreciated.

~md5sum~

A: 

You're right. If they're sealed, they can't be inherited and thus can't be serialized. You're going to have to create your own custom shape classes. I'll assume your problem with that was that you don't want to have to recreate all the methods and properties.

I suggest you create "lite" shapes (Like USA Today is "lite" news). Just put in the minimal properties needed to fully define each shape:

  • Square: Width (double), Rotation angle (double) and Center (point).
  • Rectangle: Width, Height, Center, and Rotation angle.
  • Circle: Radius (double), Center
  • Ellipse: Width, Height, Center, Rotation ... and so on.

When you deserialize them, you'll instantiate the actual System.Windows.Shapes, but you won't have to recreate the whole thing.

Rap
Won't this also require me to re-define the geometry for them? ...that was the part I really didn't want to have to do... copying the properties didn't really bother me.
md5sum
No. The geometry is immaterial when serializing. You just need the minimal amount of info to fully define the shape. IOW, you don't need to recreate a square, you just need to know where it is and how big it is. When you deserialize it, you use the System.Windows.Shape to define the geometry.
Rap
+3  A: 

Another solution is to create serialization methods, which takes shape as parameters and serialize the properties into xml or whatever you'd like. An example would be like:

/// <summary>use reflection to serialize all properties and type into an xml string</summary>
/// <param name="s">shape object to be serialized</param>
/// <return>the serialized xml string</return>
public static string SerializeShape(Shape s);

/// <summary>create a new Shape object with given xml data</summary>
/// <param name="s">xml serialization generated by SerializeShape(Shape s)</param>
/// <return>the constructed shape</return>
public static Shape DeserializeShape(string s);

You might need to change the methods a bit to better fit your objects. Worst case, you will have to create a few pairs of those serialization/deserialization methods for different shapes.

Bill Yang
Based on this advice, I created a SerializeObject(object obj) and a DeserializeObject(string s) pair of methods. I posted them on my blog for anyone to use at:http://maxaffinity.blogspot.com/2009/10/serialize-objects-manually.html
md5sum