Donald King's Blog

Implements IQuestionable

  Home  |   Contact  |   Syndication    |   Login
  3 Posts | 0 Stories | 2 Comments | 8 Trackbacks

News

Archives

Post Categories

AgileWise Articles

Technology Links

I have been trying to solve a little problem I have with controlling the serialization of a class I have inherited from CollectionBase to create a strongly typed collection. The class that drove the need for my strongly typed collection is of type HeadlinesArticle and the collection class is HeadlinesArticleCollection:
 
 
[XmlRootAttribute("Article")]
public class HeadlinesArticle
{
...
}
 
[XmlRootAttribute("Article")]
public class HeadlinesArticleCollection : CollectionBase
{
...
}

As you can see in above code, I have decorated the HeadlinesArticle class so that the serializer will write out 'Article' as the root. It works fine and produces exactly what I need. The HeadlinesArticleCollection class is somewhat different. As many of you know, the default serialization behavior for this type of class is to output something similar to this:
<ArrayOfHeadlinesArticle>
...
</ArrayOfHeadlinesArticle>
To change this behavior, I had to create a new System.Xml.Serialization.XmlRootAttribute and provide what root element I want the Serializer to use. Here's an example where 't' is of type HeadlinesArticleCollection:
 

serializer = new XmlSerializer(t, new System.Xml.Serialization.XmlRootAttribute("Articles"));

This is all fine except the Serializer ignores the root attribute decoration I placed on the HeadlinesArticle class and so instead of this:
<Articles>
<Article>
...
</Article>
<Article>
...
</Article>
<Article>
...
</Article>
</Articles>
I get this:
<Articles>
<HeadlinesArticle>
...
</HeadlinesArticle>
<HeadlinesArticle>
...
</HeadlinesArticle>
<HeadlinesArticle>
...
</HeadlinesArticle>
</Articles>

Obviously the Serializer is ignoring the root attribute I placed on the HeadlinesArticle class. So I tried using the [XmlElement] attribute on the indexer of HeadlinesArticleCollection class but it basically has no effect at all:
 


[XmlElement("Article")]
public int IndexOf( Article value )  
        {
            return( List.IndexOf( value ) );
        }

So my question is, does anyone have an idea of what I can do to get the behavior in serialization I need short of renaming the HeadlinesArticle class to Article? Renaming the class is of course a work-around but I sure hate to think that I can't name my classes what I want.

One other caveat is I considered implementing the IXmlSerializable interface which I have done before and it works but I feel I should not have to go to that length for this. Any help is appreciated.

DK

posted on Monday, July 04, 2005 10:53 PM

Feedback

# re: Controlling Serialization of CollectionBase 7/5/2005 1:05 AM Geoff Appleby
The first thing to look at is pretty obvious and hopefully only a typo in your post, not the code.

Putting the XMLElement attribute on the IndexOf method won't work, because that a method, not a property, and serialization only includes properties.

Is this a typo? You should have used the Items() property...

# re: Controlling Serialization of CollectionBase 7/5/2005 7:21 AM Donald King
Yes that was a typo. Thank you and I apologize. I placed the XmlElement attribute on:

public Article this[ int index ]
{
get
{
return( (Article) List[index] );
}
set
{
List[index] = value;
}
}

That did not work for me however. I assume that is the property you are referring to or have I missed an overridable property in CollectionBase that I should be implementing?

# re: Controlling Serialization of CollectionBase 7/5/2005 7:24 AM Donald King
BTW, in the above code you will notice that my collection is for Article instead of HeadlinesArticle. That is because I did change the name of the class to get the behavior I needed to continue on with development. As I stated in my original post, I don't prefer this work-around.

# re: Controlling Serialization of CollectionBase 7/5/2005 9:07 AM Geoff Appleby
Interesting problem.

I just had a play around to see if I could figure it out.

Nope :(

# re: Controlling Serialization of CollectionBase 7/5/2005 9:13 AM Donald King
That's cool. This is one that has me perplexed. Thanks for taking a look at it anyway and if I figure it out I will post the solution. Thanks!

# re: Controlling Serialization of CollectionBase 8/29/2005 11:34 AM Eric Matz
Do you have a class that contains the HeadlinesArticleCollection as a property? If so, you can use the XmlArray/XmlArrayItem attributes to tell the serialization engine how to behave:

[XmlArray("Articles"), XmlArrayItem("Article", typeof(HeadlinesArticle))]

But that can't be applied to a class. I suspect any serialization attributes you use in your CollectionBase-derived class will be ignored because of the special treatment given by the XmlSerializer to classes that implement IEnumerable. For example, you can't add a property to the HeadlinesArticleCollection class that serializes as an attribute. I've been trying all day and it's driving me nuts!

# re: Controlling Serialization of CollectionBase 8/29/2005 1:27 PM Donald King
Eric - Thanks for the feedback. I posed the question to an XML MVP and he basically said the same thing. Looks like I can either go that route or I will need to rename my classes. That is not preferable. Thanks again!

# re: Controlling Serialization of CollectionBase 1/7/2008 4:06 PM Himanshu R. Swami
You want to apply the XmlArray/XmlArrayItem attributes to the HeadlinesArticle class instance declaration, not the class definition. So, for example:

[XmlRoot("MyClass")]
public class MyClass
{
[XmlArray("Articles")]
[XmlArrayItem("Article", typeof(HeadlinesArticle))]
public HeadlinesArticleCollection Articles;
}

Normally, you would have the HeadlinesArticleCollection defined within a larger class/structure - the MyClass definition here is a stand-in for your larger class/structure. Alternatively, you can define:

[XmlRoot("Articles")]
public class MyClass
{
[XmlElement("Article", typeof(HeadlinesArticle))]
public HeadlinesArticleCollection Articles;
}

Unfortunately, there is no way around the "container" class/structure for this. That is because the XmlArrayAttribute, XmlArrayItemAttribute, and XmlElementAttribute attributes can only be applied to fields/properties, not classes.

# re: Controlling Serialization of CollectionBase 8/18/2008 5:38 PM Josh Heming
The only workaround is to explicitly implement IXmlSerializable in your class . This isn't very difficult but it can add some development overhead if you want to modify your class definition later.

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: