XAML in .Net 4.0: Serialization and Deserialization using XamlServices

Serialization and Deserialization using XamlServices

Note: This post is based on Visual Studio 2010 Beta 1 which is the latest version available in the time of writing this post, so by the time this technology ships, there are probably things that will be slight different.

In order to serialize and deserialize using XAML in .Net Framework 4.0 we have to reference a new assembly called System.Xaml.dll. Since XAML was originally used only in WPF, some features are dependent on classes that are inside WindowsBase.dll.

Serialize to Xaml with XamlServices

Assuming we have a class called Book, that is defined like this:

public class Book

{

  public string Name { get; set; }

  public int ISBN { get; set; }

}

In order to serialize it, we use System.Xaml.XamlServices class:

Book book1 = new Book { Name = "First", ISBN = 123 };

string bookFileName = "book.xaml";

using (TextWriter writer = File.CreateText(bookFileName))

{

  XamlServices.Save(writer, book1);

}

The output file should contain the following content:

<Book ISBN="123"

    Name="My first book"

    xmlns="clr-namespace:XamlSamples;assembly=XamlSamples" />

If we have a more complex object graph, for example if each book had a list of related books:

public class Book

{

  ...

 

  private IList<Book> related = new List<Book>();

  public IList<Book> Related { get { return this.related; } }

}

Then for the following books with relations:

Book book1 = new Book { Name = "First", ISBN = 123 };

Book book2 = new Book { Name = "Second", ISBN = 456 };

Book book3 = new Book { Name = "Third", ISBN = 789 };

book1.Related.Add(book2);

book1.Related.Add(book3);

book2.Related.Add(book1);

book3.Related.Add(book1);

The result will be:

<Book x:Name="__ReferenceID0" ISBN="123" Name="First"

    xmlns="clr-namespace:XamlSamples;assembly=XamlSamples"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Book.Related>

        <Book ISBN="456" Name="Second">

            <Book.Related>

                <x:Reference>__ReferenceID0</x:Reference>

            </Book.Related>

        </Book>

        <Book ISBN="789" Name="Third">

            <Book.Related>

                <x:Reference>__ReferenceID0</x:Reference>

            </Book.Related>

        </Book>

    </Book.Related>

</Book>

Notice that the first book is now being identified using the x:Name property and its unique id is __ReferenceID0. This ID is also used to list the related books of the second book. Also note that there is no need to create a unique id to the second book because it is represented as a child element of the first one.

If we wanted to use the Name property of the books as the unique identifier, we could use the System.Windows.Markup.RuntimeNamePropertyAttribute in WindowsBase.dll:

[RuntimeNameProperty("Name")]

public class Book

{

  ...

}

Now, the output will be:

<Book ISBN="123" Name="First"

    xmlns="clr-namespace:XamlSamples;assembly=XamlSamples"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Book.Related>

        <Book ISBN="456" Name="Second">

            <Book.Related>

                <x:Reference>First</x:Reference>

            </Book.Related>

        </Book>

        <Book ISBN="789" Name="Third">

            <Book.Related>

                <x:Reference>First</x:Reference>

            </Book.Related>

        </Book>

    </Book.Related>

</Book>

Note that there is no x:Name attribute.

If we also want to take out the <Book.Related> nodes, and set its content to be the content node of the Book type, we can use the System.Windows.Markup.ContentPropertyAttribute in WindowsBase.dll.

[RuntimeNameProperty("Name")]

[ContentProperty("Related")]

public class Book

{

  ...

}

Now, the result is much simpler:

<Book ISBN="123" Name="First"

    xmlns="clr-namespace:XamlSamples;assembly=XamlSamples"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Book ISBN="456" Name="Second">

        <x:Reference>First</x:Reference>

    </Book>

    <Book ISBN="789" Name="Third">

        <x:Reference>First</x:Reference>

    </Book>

</Book>

Deserialize from Xaml with XamlServices

In order to deserialize an object graph from .xaml file, we can use XamlServices.Load method:

using (TextReader reader = File.OpenText(bookFileName))

{

  Book book = (Book)XamlServices.Load(reader);

  Console.WriteLine("Book {0} (ISBN:{1})", book.Name, book.ISBN);

  Console.WriteLine("Related Books:");

  foreach (Book relatedBook in book.Related)

  {

    Console.WriteLine("\t{0} (ISBN:{1})", relatedBook.Name, relatedBook.ISBN);

  }

}

After deserialization, the object graph is just as it was before serialization, and the output is:

Serialization and Deserialization using XamlServices

Summary

In this post I showed basic samples of serialization and deserialization of object graphs uisng XamlServices in System.Xaml as part of the .Net Framework 4.0. In later post I'll talk about some more advanced features such as Attached Properties and more.