views:

62

answers:

6

I have the following class structure (not simplified btw):

[Serializable]
[XmlInclude(typeof(Twitter))]
[XmlInclude(typeof(LinkedIn))]
public abstract class SocialNetworkBase : ISocialNetwork
{
    public abstract string UserName { get; set; }
}

public class Twitter : SocialNetworkBase
{
    public override string UserName { get; set; }
}

public class LinkedIn : SocialNetworkBase
{
    public override string UserName { get; set; }
}

And then I am trying to serialize a list of 'SocialNetworkBase' like:

new XmlSerializer(typeof(List<SocialNetworkBase>)).Serialize(ms, socialNetworks)

Which returns

<?xml version="1.0"?>
<ArrayOfSocialNetworkBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <SocialNetworkBase xsi:type="LinkedIn">
    <UserName>someUsername</UserName>
  </SocialNetworkBase>
</ArrayOfSocialNetworkBase>

When trying to deserialize using:

return new XmlSerializer(typeof(List<SocialNetworkBase>)).Deserialize(ms) as List<SocialNetworkBase>;

The following error is thrown:

There is an error in XML document (0, 0). ("Root element is missing.")

What is going on here? Deserializing to SocialNetworBase[] throws the same error.

A: 
typeof(SocialNetworkBase[])

maybe?

IIRC, you need to have some container object (but I havent done this is ages, so I can't recall).

leppie
A: 
[Serializable]
public abstract class SocialNetworkBase : ISocialNetwork
{
    public abstract string UserName { get; set; }
}

[Serializable]
public class Twitter : SocialNetworkBase
{
    public override string UserName { get; set; }
}

[Serializable]
public class LinkedIn : SocialNetworkBase
{
    public override string UserName { get; set; }
}

Maybe?

LnDCobra
+1  A: 

Your problem is your memory stream. After serializing data into it, its cursor is at the end of the stream. If you want to use it (for deserializing purpose, for example), you need to set the cursor back to the begining of the stream:

ms.Seek(0, SeekOrigin.Begin);
sagie
Was already doing that :-)
Jan Jongboom
@jan: Please clear this up: Do you get the same error after using Seek()?
Henk Holterman
A: 

Jus a side note. (Stream position seems to be the issue and has been answered)

I noticed the use of the [Serializable] ontop of the classes. We don't need those for the functionality you are describing. The 'Serializable' attribute is used with the 'System.Runtime' serializers (or Formatters if you prefer that naming convention). The XmlSerializer used here does not require (or use) the [Serializable] attribute.

The XmlSerializer can serialize ANY type when: -It's a public type and has a public default constructor

Marvin Smit
A: 

Take a look at this other question, it looks that it might be useful.

XML Serialization and Inherited Types

João Angelo
A: 

As I was already passing by the ms.Position = 0 this wasn't the issue. However, when ditching the StreamWriter I used earlier in favor of:

byte[] buffer = Encoding.UTF8.GetBytes(socialNetworks);
ms.Write(buffer, 0, (int)buffer.Length);

The problem went away for some reason.

Jan Jongboom
socialNetworks is a string???? Update your question with this info, don't post an answer.
Hans Passant