This post is in response to Marc Clifton's blog entry describing the new MyXaml parsing logic. I have been working with Marc on a MyXaml serializer/deserializer for VG.net vector graphics. I work on the serializer, and Marc, of course, works on a generic deserializer (markup->objects). During this process, we realized XAML is a poor general purpose serialization format; it is optimized only for Avalon. Read Marc's blog for all the details.
As a result, MyXaml is evolving into a format designed specifically to support the designer infrastructure already available in the .NET framework. This will make MyXaml extremely powerful! As far as I can tell, this infrastructure support was ignored during the design of XAML.
In just a few days, we were able to create a VG.net serializer (invoked from the designer) producing MyXaml files functionally equivalent to code produced by the CodeDom serializer. Such a task would have been difficult using the XAML format, and the resulting markup would be ugly. Our plan is to make MyXaml the main xml serialization format for VG.net.
One great thing about the VG.net serializer is the general nature of the code: it is not so much a VG.net serializer, as a generic serializer for any components built according to the .NET designer serialization guidelines. If your component supports Visual Studio .NET CodeDom serialization, it will support MyXaml serialization!
I will write some additional blog entries describing how to create a MyXaml serializer. First, I will explain the different types of properties a generic serialization engine must support, and some complications for the MyXaml format.
There are three types of serialized properties in .NET, corresponding to the three types of DesignerSerializationVisibilityAttribute values:
- Visible, the default value for writable public properties. These can be serialized in xml either as string values, in tag attributes, or by using the class-property-class syntax. Within the VG.net serializer, we serialize a property to an xml attribute if the property Type has a corresponding TypeConverter that can convert from a string: <Rectangle Name=“Rect1“>. Otherwise, we use the class-property-class syntax, with a separate tag for the property name and the property value.
- Hidden. These are never serialized.
- Content. Used for read-only properties that need sub-properties serialized. Typically used for collection properties, Content means the property is not deserialized by creating an object and assigning it to the property. The property is usually read only, making assignment impossible.
We can divide Content properties into two categories:
- Collections, which are deserialized via Add or AddRange calls.
- Read-only properties that are not collections. These rare properties are deserialized by assigning values to the object returned on a property get: rootObject.A.B = value. In that example, the property A is read-only, and cannot be assigned, but we still need to serialize and deserialize properties within A, namely B.
Now, you may be wondering about this class-property-class syntax. If you don't want to look back at Marc's blog, here is a summary. At the top level, a tag specifies a class. Each tag below that specifies a property name. Each tag within a property tag specifies a class, the value for that property:
<SolidFill Color=”Blue” />
What should the syntax be for Content properties? For collections, Marc decided to place the items in the collection underneath the property tag. Implicitly, these objects are added to the collection:
<Rectangle Name="rectangle1" Location="480, 280" Size="100, 80" />
<Rectangle Name="rectangle2" Text="Hello!" Location="300, 300" Size="100, 80" />
The only problem with this approach is setting other properties in a collection. A collection may have other properties that need to be serialized in addition to the items. And one of the property names could conflict with an item class name. I see two ways to resolve this: either use an additional tag level, called Items, for the items, or use the compound property syntax for collection properties.
How should Content properties that are not collections be serialized? I don't think there are any such properties in VG.net. But a generic way to serialize such properties might be be to use the same format as a collection: first the property tag, then the properties within the Content property. There is no need to output another tag level for an object to assign to the Content property, since it is read only. In this example, A is a Content property within RootClass, and B a property within that
<B> ... values for B ...
This is easy to serialize and deserialize, but may throw off readers of the markup, since Content properties have one less level of tags then other properties. For consistency, it might be better to have that extra level, even though no object can be created and assigned to the Content property (in this example, A is read-only):
<B> ... values for B ...