Thursday, September 09, 2010

Populating an Existing Object Using Xaml2009

When doing Xaml-based development, it is often necessary, or at least convenient, to use Xaml to configure a preexisting object.  For instance, we often want to allow a Xaml-declared object to be created simply by calling a standard object constructor from C# code.  That constructor then calls into an API that loads in a Xaml file and populates the fresh object instance.  This is, in fact, how the UserControland Window item templates in Visual Studio are set up to work: the C# code-behind declares a default constructor which calls a designer-generated InitializeComponent() method, which in turn calls Application.LoadComponent(), which takes in both the control instance and a URI pointing to a Xaml resource.  It then loads the specified Xaml file and populates the control.

As most Xaml developers know, .NET 4 shipped with a whole new Xaml subsystem (System.Xaml), which supports the new Xaml2009 language specification.  Xaml2009 documents may be read and written from the XamlServices class.  However, none of the available Load methods will populate an existing object instance.  Fortunately, this capability does exist and is conveniently exposed by the XamlObjectWriterSettings class (thanks to @rrelyea for pointing that out!).  Since I use Xaml for all manner of things outside of WPF, I found it convenient to write a utility class to assist in populating existing objects.  I implemented corresponding methods for all of the XamlServices.Load() overloads, and even XamlServices.Parse().  I provide that code below for anyone to use as they see fit.

   1: using System.IO;
   2: using System.Xml;
   3:  
   4: namespace System.Xaml
   5: {
   6:     public class XamlExtensions
   7:     {
   8:         public static object LoadInto(object instance, string fileName)
   9:         {
  10:             if (instance == null)
  11:                 throw new ArgumentNullException("instance");
  12:             if (fileName == null)
  13:                 throw new ArgumentNullException("fileName");
  14:  
  15:             using (var xmlReader = XmlReader.Create(fileName))
  16:             {
  17:                 var xamlReader = new XamlXmlReader(xmlReader);
  18:                 return LoadInto(instance, xamlReader);
  19:             }
  20:         }
  21:  
  22:         public static object LoadInto(object instance, Stream stream)
  23:         {
  24:             if (instance == null)
  25:                 throw new ArgumentNullException("instance");
  26:             if (stream == null)
  27:                 throw new ArgumentNullException("stream");
  28:  
  29:             using (var xmlReader = XmlReader.Create(stream))
  30:             {
  31:                 var xamlReader = new XamlXmlReader(xmlReader);
  32:                 return LoadInto(instance, xamlReader);
  33:             }
  34:         }
  35:  
  36:         public static object LoadInto(object instance, TextReader textReader)
  37:         {
  38:             if (instance == null)
  39:                 throw new ArgumentNullException("instance");
  40:             if (textReader == null)
  41:                 throw new ArgumentNullException("textReader");
  42:  
  43:             using (var reader = XmlReader.Create(textReader))
  44:             {
  45:                 var xamlReader = new XamlXmlReader(reader);
  46:                 return LoadInto(instance, xamlReader);
  47:             }
  48:         }
  49:  
  50:         public static object LoadInto(object instance, XmlReader xmlReader)
  51:         {
  52:             if (instance == null)
  53:                 throw new ArgumentNullException("instance");
  54:             if (xmlReader == null)
  55:                 throw new ArgumentNullException("xmlReader");
  56:  
  57:             using (var xamlReader = new XamlXmlReader(xmlReader))
  58:             {
  59:                 return LoadInto(instance, xamlReader);
  60:             }
  61:         }
  62:  
  63:         public static object LoadInto(object instance, XamlReader xamlReader)
  64:         {
  65:             if (instance == null)
  66:                 throw new ArgumentNullException("instance");
  67:             if (xamlReader == null)
  68:                 throw new ArgumentNullException("xamlReader");
  69:  
  70:             var xamlWriter = new XamlObjectWriter(
  71:                 xamlReader.SchemaContext,
  72:                 new XamlObjectWriterSettings
  73:                 {
  74:                     RootObjectInstance = instance
  75:                 });
  76:  
  77:             XamlServices.Transform(xamlReader, xamlWriter);
  78:             return xamlWriter.Result;
  79:         }
  80:  
  81:         public static void ParseInto(object instance, string xaml)
  82:         {
  83:             if (instance == null)
  84:                 throw new ArgumentNullException("instance");
  85:             if (xaml == null)
  86:                 throw new ArgumentNullException("xaml");
  87:  
  88:             var input = new StringReader(xaml);
  89:  
  90:             using (var xmlReader = XmlReader.Create(input))
  91:             {
  92:                 var xamlReader = new XamlXmlReader(xmlReader);
  93:                 LoadInto(instance, xamlReader);
  94:             }
  95:         }
  96:     }
  97: }

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home