You may follow this code @ serializableex.codeplex.com.
Introduction
This is an updated article and code base from my original publication [Serialization for Rapid Application Development: A Better Approach] here at CodeProject. After several years of growth in ability and advances in technology, I decided it was time to update that code base and article for use in .NET 4. The result of this is a much smaller code base, unit tests to back them up, and fixes to some issues concerning discovery within a web environment.
Background
In short, the problems with the XmlSerializer
that existed when I wrote the first article still exist today. They are classic issues that there is still no unified approach in dealing with. The major problem is still how do you resolve unknown classes when serializing and deserializing.
There have been several attempts that I've followed over the years to get around this, anywhere from the creation of entire frameworks like YAXLib to instructions on how to make use of the IXmlSerializable
interface at various levels of sophistication.
With all of these solutions, the major problem from a developer perspective that has always crept in is cumbersomeness of the implementation. IXmlSerializable
asks the developer to write some form of a customized implementation per class. YAXLib and others ask the developer to use different attributes, or handle outputs that don't look like the clean(ish) XML generated by XmlSerializer
. The [XmlInclude(Type type)]
attribute demands that all types to be serialized be within the same library. None of them (that I know of) in my opinion relieves the developer from the tedium of working with these solutions.
Goals Realized
Serializable Extra Types is designed to be as thoughtless as possible with an absolute minimum of development consideration. What it does is make use of the standard XmlSerializer
and a slightly un-hyped overloaded constructor; it has to incorporate extra type definitions for use in type resolution during serialization and deserialization.
It is actually a very simple idea. Keep a list of all the possible types that the XmlSerializer
may have need of during a serialization/deserialization process. Register those types using attribute adornments and provide some Extension Methods to make incorporating those lists thoughtless to the developer.
It works under a parent child relationship. I can best describe it as saying, it's the reverse of the XmlInclude
attribute. The XmlInclude
attribute is placed on a class to give the serializer knowledge of other classes when serializing the class that is adorned. SerializableExtraType
is placed on a class to give the other class knowledge of the adorned class when the other class is serialized.
So...
XmlInclude = Parent => Child
SerializableExtraType = Child => Parent
This allows the SerializableExtraTypes
code to integrate related classes across libraries. Additionally, I have exposed a method by which you may register additional relationships at runtime. This solves any situation that you may come across with libraries and applications having complex implied relationships.
Using the code
The code is available in the download and at the CodePlex site. Both have a series of test libraries and a consuming test project that shows the usage very well. Here I will outline the quick and dirty of how to make use of it.
First, adorn a class with the required attribute like this:
[SerializableExtraType(typeof(Foo))]
[SerializableExtraType(typeof(SomethingElse))]
[SerializableExtraType(typeof(ClassOne), typeof(ClassTwo))]
public class Foo { public Foo() {} }
The Extension Methods make use of the SerializableExtraTypes
under System.Xml.Serialization
.
Now make use of the Extension Methods to serialize and deserialize objects.
string xml = new Foo { ClassList = {new ClassOne(), new ClassTwo(), }, }.SerializeEx();
Foo obj = "<Foo><ClassList><ClassOne /><ClassTwo /></Foo>".DeserializeEx<Foo>();
string xml = new SomethingElse { ObjectList = { new Foo(), new Foo(), }, }.SerializeEx();
SomethingElse obj = "<SomethingElse><ArrayOfObject><Foo />" +
"<Foo /></ArrayOfObject></SomethingElse>".DeserializeEx<SomethingElse>();
There is more functionality built into the code base but this is a quick and dirty sample. Please take a look at the download for further examples.
History
This is the second publication of this method. Please send any comments or suggestions on how to improve it. You can email me at danatcofo@gmail.com.