Cleaning up XmlWriter and IXmlSerializable with Extension Methods

by jmorris 11/4/2009 4:46:00 AM

If you do any work with xml you probably have come across scenarios where you are using an XmlWriter to produce an output stream of xml. Eventually this output stream is either persisted to disk via an XDocument, sent over the wire using a distributed technology such as WCF, Remoting etc., or possibly transformed with XSL/XSLT. A strong example is custom serialization classes that implement IXmlSerializable.  For example:

The class above is a simple data transfer class (DTO) that implements IXmlSerializable so that it can be serialized and/or deserialized from an objet to an xml stream and vice versa. Note: in most cases you would simple mark the class as [Serializable] and/or provide attributes from the System.Xml namespace to provide the same behavior, however in many cases the default implemention will not fit your particular scenario, hence you would implement IXmlSeriable and provide your own custom serialization.

Here is the 'custom' serialization implementation:


While the XmlWriter/XmlReader API's are pretty simple to use, they are also a bit verbose. If you happen to have a fairly large class with many fields, things start to get ugly pretty fast. Typically when I see large classes, I began to think about refactoring into smaller classes when applicable, but that not always the case. Since, most of them time when want serialization/deserialization you simple want to quickly (i.e. less keystrokes) turn the contents and structure of the class into its xml equivalent you are looking at reducing the amount of work needed. This is where extension methods really come in handy:



The result compared to above is a much cleaner, easier to read class:


While extension methods are not new, they do offer unique way of handling situations where you would like to simplify a set of operations without reaching for the traditional static xxxUtil class or creating a customized implementation or wrapper class. In this case,  XmlWriter is a class open for extension via basic inheritance, unlike a sealed class such as System.String, which is the intended purpose of extension methods: extended classes closed to inheritance (sealed).

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , , , , ,

C# | XML

DataMapper Pattern Implementation with XML and Attributes

by jmorris 7/21/2009 7:17:00 AM

The DataMapper Pattern is a well documented and defined pattern for abstracting away an object’s storage from its in-memory representation. For the most part the pattern explicitly defines the domain of the pattern to be relational databases and object’s that map to there schema, however the pattern is adaptable to non-relational data-stores as well. In fact to applicable to any situation where the need to map records (related data units) to in memory objects; regardless of structure or underlying store.

Imagine, for instance, a service that is a façade for a complex matrix of unstructured key value pairs and a protocol for clients to query the service for tuples. For example:

  • For the make ‘honda’, give me all ‘years’ 
  • For the article ‘2311’, give me ‘title’, ‘description’, ‘author’, ‘publication_date’

This is not too much different from any relational database model, with the exception that there is no direct joining occurring to return back columns that occur in different tables and relate them to the input set. It’s basically just a giant hash-map of name/values pairs with an undefined structure…i.e. there is no way to directly map it to a domain model; what you supply as inputs, defines the structure of your output.

That’s where the DataMapper Pattern comes into play. According to Fowler, the DataMapper is a “a layer of Mappers that move data between object and a database while keeping them independent of each other and mapper itself”. The core motivation behind the pattern is separation of concerns; an abstraction between the data, the store, and entity objects themselves. By using a DataMapper we can associate the name/value pair scenario described above with our domain objects, providing structure to our model. This is important because we go from an untyped hash-map model to tangible objects (POCO) that are typed, thus allowing us the benefits of developer friendly features of our IDE, such as ‘intellisense’ and compile time type safety.

Implemented within an API, you get something that looks like the following:

Think of it as a minimalistic ORM. In this case such concerns as caching and transactions are the responsibility of the underlying data-store service. As a consumer we are only concerned with making a request for data, getting a result set, and mapping it to an entity or domain object. In the diagram above, there are actually three different patterns working to create the whole: the command pattern, the repository pattern, and the data mapper pattern. All three comprise the entire API.

A Simple DataMapper Implementation:
This implementation of a DataMapper really does just three things: a) it reads through an XML stream, b) it maps to the values of specific XML attributes to an associated property, and c) packages the results into either a collection or a single object of the Type provided defined in the generic argument:

Map maps a single result to a single object. MapAll maps multiple results to a list of objects, and Read is a private method that extracts all key value pairs (XML attributes and there associative values) to a dictionary.

All Read does is extract out the XML attribute names and there associative data and store them in a dictionary. The dictionary is then used by the Map and MapAll methods along with a System.Attribute class to map the values directly to the correct properties:

In the code snippet above, after the Read method has extracted the data for mapping we loop over each of the objects properties looking for a FieldMappingAttribute on each of the properties we have flagged for mapping. If a match is found the relevant data is mapped directly to the object’s property and then the object is returned.

 

MapAll does essentially the same as Map, but assumes that the stream contains more than one object definition and then returns the resulting collection.

A couple of things to note here, the code a) needs a little refactoring to improve performance and extensibility, b) we are assuming a relatively flat xml file streamed here, no nesting of elements for example and c) we are only supporting properties of the Type System.String . The simplicity is purposeful…when I need it I’ll add it.

One last thing to discuss is implementation of FieldMappingAttribute and its usage. FieldMappingAttribute is a simple class deriving from System.Attribute that allows us to decorate properties on our entity classes with attributes that define our mapping schema:

The usage is pretty simple and should be familiar to most .NET developers:

References:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

C# | Software Patterns | XML

XSLT Transformation Extension for XDocument

by jmorris 6/15/2009 7:49:00 AM

I needed to update a utilities class I have been using to support XDocument (not just XmlDocuments) when I hit upon creating an extension method instead of the typical static utility class/method approach. Extension methods are a simple and powerful means of adding behavior to existing classes without breaking encapsulation. I was initially skeptical of the idea, but they have turned out to be rather nice and syntically better than static utilities classes.

The XDocument class is key part of the LINQ to XML API released with .NET Framework 3.5. Essentially it's a 'next' generation replacement for the XmlDocument class with added functionality for easily modifying in-memory Xml documents. Overall I prefer XDocument over XmlDocumentfor various reasons, but learning a new API can be a bit frustrating; it takes time to build a knowledge base of all of the 'gotchas' and 'hacks' ;)

Anyways, here is the final result:



Note that by convention I named the class after the class I was extending and added the 'Extensions' post fix. This makes things a little easier to manage. Here is the usage:

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , , ,

XML

Root element is missing and XDocument and SeeOrigin.Begin

by jmorris 5/5/2009 11:45:00 AM

I was writing some unit tests for a project I am currently working and kept getting the following non-useful exception:

I have seen the error before many times in the past, but I could not put my finger on what was causing it. The code is pretty simple, it just creates and instance of an object that implements IXmlSerializable passing in a stream which internally adds additional chicled object to the stream and then loads the result into a XmlReader. The the XmlReader then outputs the results to the standard console (note that a little later I add assertations to validate that the data was 'extracted' correctly):

 

Needless to say, this code failed every time on XDocument.Load with the 'Root element missing' exception.  I vaguely remember getting this error sometime in the past, but couldn't put my finger on it. I finally ran across this blog post and a light bulb went off.



After writer.Flush() is called the position of the stream is EOF. Before you can read the stream you must set the position of the stream to the begining. Note that calling writer.BaseStream.Position = 0 does _not_ work. You must call writer.BaseStream.Seek(0, SeekOrigin.Begin) to reset the streams position before creating the reader and loading the XDocument object. Also, note that the error only occurs because the XDocument object thknks the XML stream is invalid.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

C# | XML

Powered by BlogEngine.NET 1.3.1.0
Theme by Mads Kristensen

Jeff Morris

Name of author Occasional rants about software development and software engineering in general.

E-mail me Send mail

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar

Pages

    Recent comments

    Authors

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010

    Sign in