Serializing an Object Tree

Posted on March 19, 2009. Filed under: WPF | Tags: , , , |

If you look at it closely, XAML is actually just a language that describes how to instantiate objects. Only that in most of the cases it is used to describe objects from the System.Windows.Controls namespace. When a project contains a .xaml-file, the compiler compiles it into a binary format called BAML (hard to guess – Binary XAML). The .xaml doesn’t directly go into the assembly file, it’s the BAML file that does.

Even if you can’t produce BAML manually, it is possible to leverage some of the XAML-infrastructure’s power for your own purposes: With the XamlReader and XamlWriter classes (both are located in the System.Windows.Markup namespace), you can serialize an arbitrary object tree into any stream (or even a string). The XamlWriter offers a single static method that basically takes an object and serializes it by serializing all of its properties. If a property has a type like string or double, the string representation of its value becomes an attribute of the xml-node. If the property is a complex object itself, it is serialized just like the first object: By analyzing all of its properties.

Since there is no way of passing arguments to functions in XAML, all of the serialized objects must be objects of types that have a parameterless constructor.

Collections

The XamlWriter recognizes collections serializes each object of the collection individually, making it a child element of the collection. The only caveat is to avoid generic collections, since they are not supported by XAML (even if a Collection<String> is resolved to something that looks like a Collection1[`String] at runtime). So if you want a collection to be serialized, you have to inherit from the Collection<TEntity> base class or any other class that implements the IList<T> interface.

   1: public class Person
   2: {
   3:     public string Name { get; set; }
   4:
   5:     public DateTime Birthday { get; set; }
   6:
   7:     public PersonCollection Children { get; set; }
   8: }
   9:
  10: public class PersonCollection : Collection<Person>
  11: {}

A serialized instance of the Person class, obtained using the XamlWriter.Save() method, might look like this:

   1: <Person Name="Franz Joseph I." Birthday="1830-08-18" xmlns="clr-namespace:XamlWriterSample.Persons;assembly=XamlWriterSample">
   2:     <Person.Children>
   3:         <Person Name="Sophie Frederike" Birthday="1855-03-05">
   4:             <Person.Children>
   5:                 <PersonCollection />
   6:             </Person.Children>
   7:         </Person>
   8:         <Person Name="Gisela Louise Marie" Birthday="1856-07-12">
   9:             <Person.Children>
  10:                 <PersonCollection />
  11:             </Person.Children>
  12:         </Person>
  13:     </Person.Children>
  14: </Person>

The xaml-Writer includes the root namespace and the assembly in the xmlns-attribute. It also references other namespaces if necessary.

The Content Property

If you decorate your class with the ContentProperty attribute, you can declare a property to be the default content property. That way, if you write your own object tree in xaml and you add a child node to your object, it is treated as a value for the content property. This property is not actually used by the XamlWriter class.

It is also possible to add the AmbientAttribute to one or more properties. If a property is declared ambient, its value will be applied to all properties of child objects with the same property if it is declared ambient as well. It is important do add the AmbientAttribute to both parent and child classes so that the XamlReader can set up an ambience transaction when it instantiates the objects.

Advertisement

Make a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Liked it here?
Why not try sites on the blogroll...

Follow

Get every new post delivered to your Inbox.