Using XAML for Custom Object Graphs

XAML is best known for its use with WPF/Silverlight, but the XAML parser is also a powerful generic serialize/deserialize tool for many .NET object graphs.  For example, XAML is used for Windows Workflow (WF).  This post will show a basic example and some tips to use XAML parsing in your own code.

Button-DownloadCode-Small SampleXamlParser.zip

Tips to Watch Out For

  • If you put a .xaml file in your VS project, be sure to set it’s "Build" property to "None" (from the default of "Page").  If you don’t VS will cause a build error on the XAML line where your assembly is defined.
  • All objects must have a public constructor with no parameters.

Sample XAML
Notice how there are a number of various objects defined here…

<col:ArrayList

  xmlns:x="clr-namespace:SampleXamlParser;assembly=SampleXamlParser"

  xmlns:sys="clr-namespace:System;assembly=mscorlib"

  xmlns:col="clr-namespace:System.Collections;assembly=mscorlib">

  <sys:String>George</sys:String>

  <sys:String>Henry</sys:String>

  <sys:String>Joe</sys:String>

  <x:Person FirstName="Frodo" LastName="Baggins">

    <x:Person.Address>Bag End, Shire</x:Person.Address>

    Carried the One Ring to Khazad Doom.

  </x:Person>

  <sys:Boolean>True</sys:Boolean>

</col:ArrayList>

 

Code to Read/Write
Some sample code that reads the above XAML and shows the objects contained in it.

using System;

using System.IO;

using System.Linq;

using System.Collections;

using System.Windows.Markup;

 

namespace SampleXamlParser

{

  [ContentProperty("Comments")]

  public class Person

  {

    public string FirstName { get; set; }

    public string LastName  { get; set; }

    public string Address   { get; set; }

    public string Comments  { get; set; }

 

    static void Main(string[] args)

    {

      // Write an object to a .xaml file

      DateTime dt = DateTime.Now;

      File.WriteAllText("out.xaml", XamlWriter.Save(dt));

 

      // File containing the XAML object graph to rehydrate

      string file = @"..\..\MyXaml.xaml";

 

      // The magic line of code that rehydrates the object graph

      ArrayList al = XamlReader.Load(File.OpenRead(file)) as ArrayList;

 

      // Show the types of objects retrieved

      foreach (object os in al)

      {

        if (os is string) Console.WriteLine(os);

        else if (os is Person) Console.WriteLine(os.ToString());

        else Console.WriteLine(String.Format("{0}, {1}", os.GetType(), os));

      }

 

      // Pause the console for debugging

      Console.WriteLine("\nPress any key to quit…"); Console.ReadKey();

    }

 

    public override string ToString()

    { return ObjectInfo(this); }

 

    string ObjectInfo(object o)

    {

      // Format a simple object to a string using

      // reflection, just show its name and properties

      return String.Format("[{0} = {1}]", o.GetType().Name,

        String.Join(", ", o.GetType().GetProperties().Select(

        a => String.Format("[{0} = {1}]", a.Name,

          a.GetValue(o, null))).ToArray()));

    }

  }

}

Of course there could be improvements to this little bit of code, like wrapping IDisposable objects such as FileStream in a using statement, improving the LINQ that outputs object type information, and more, but the point is to convey the key concepts.

Type Converter Update: If you have immutable classes (eg: Point, DateTime, Rectangle, etc) or just wish to provide simple conversion from a string to your type (and the reverse), check out the TypeConverter pattern.  The XAML parser will then use the converter.  In the above example, when DateTime gets serialized to XAML a TypeConverter is actually in play.  Here is an update to the code above with a TypeConverter: SampleXamlParser-TypeConverter.

Fun question: What are some of the advantages of using XAML parsing instead of
"plain Jane" XML serialization (using XmlSerializer)? (ex: ability to using binary XAML (BAML))

Resources

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>