Geeks With Blogs
Stefan Barrett blog

Still working on my query generator, and thought I would do the load/save logic so that I don't have to rebuild the same queries again and again during testing.
Ok, so I have a class like this:

public  class FieldContainer
{
 private List<BasicField> fields;

 public void Load()
 {}

 public void Save()
 {
  ...........
 }
}

So I figured the fastest way would be to serialize it out to a xml file.
Obvious problem; what the list contains is objects which inherit from BasicField, and during serialization they can't be resolved (because the serialization code only knows about basicField). The exception message says to use XmlInclude or some soap attribute. However, I don't want to use those attributes on my BasicField definition itself (don't want the base class to know about any inherited classes), and unfortunately they can't be used on properties, so I can't put them on the field definition itself.
A bit of further research found XmlArrayItem, which I could apply to the collection:
So, I had:

 [XmlArrayItem(typeof(DataField)), .... ]
 public List<BasicField> fields;

But this presented another problem. The clue is in the de-serialization code:

 XmlSerializer xs = new XmlSerializer(typeof(List<BasicField>));
 StreamReader sr = new StreamReader("Fields.xml");
 data = (List<BasicField>)xs.Deserialize(sr);
 sr.Close();

There's no way to tell the deserialization about the inheriting classes. Ok, so the XmlSerializer does raise events if it does not understand something (e.g. UnknownElement), but that seemed to more extra work. Also, I would be using the attributes for saving and the events for loading, messy.
In the end, I created another class which just has the List in it, and then serialize that class.

 public class DataWrapper
 {
  [XmlArrayItem(Type=typeof(DataField)),   .....]
  public List<BasicField> AllFields = new List<BasicField>();
 }

This way the XmlSerializer can work out all the types. So everything fixed, I ran the code again. Failed again.
When serializing, I got a

System.InvalidOperationException: The type System.String may not be used in this context.

This seems to be generated when the generated serializing assembly tries to serialize the first item in my list.
Used XmlIgnore (to stop the serialization of individual properties) on the properties to 'debug' the situation (since you can't access the code which does the actual serialization, this seems to be the easiest way?), and tracked the problem down to this: 

public System.Type FieldType;

A property which returned 'Type'. At first, I had to wonder why the exception mentions string. So I thought, that's odd, I guess that means 'Type' is not serializable. Mmmmm... Ahhh.. Of course, the problem is rather similar to my first problem. Because the actual type stored is not actually Type, but rather a type which inherits from Type.
Wanting a fast answer, I added XmlIgnore to the FieldType property, and added another property:

 public string FieldTypeString
 {
  get
  {
   return FieldType.ToString();
  }
  set
  {
   FieldType = Type.GetType(value);
  }
 }

Since at run-time all the used types are resolable. Through I do wonder if there's any other way of doing it?

It's been to long since I've done serialization, but it tends to be one of those things which you do a lot of, and then don't touch for a year.


While running through the problem, got plenty of exceptions, which allowed me to explore the exception window.. Which is not quite as good as I thought initially, particularly when getting serializing exceptions, it's not really giving me much. I always have to click on Inner Exception.
Also the 'Get general Help for this exception' only does the outer exception, no the inner one.

Posted on Sunday, April 9, 2006 9:41 AM VS2005 | Back to top


Comments on this post: Serialization

# re: Serialization
Requesting Gravatar...
Serialization doesn't like polymorphism all that well. You might try looking at StructureMap at http://structuremap.sourceforge.net as a way to configure polymorphic arrays in configuration. It will be able to handle a jagged array much easier than serialization.
Left by Jeremy on Apr 09, 2006 11:08 AM

# re: Serialization
Requesting Gravatar...
A SoapFormatter should do the trick. You'll have to implement ISerializable, but it's worth it. I used it in a situation where I was dealing with a complex object hierarchy.
Left by Anthony Trudeau on Apr 10, 2006 12:11 AM

Comments have been closed on this topic.
Copyright © Stefan Barrett | Powered by: GeeksWithBlogs.net