views:

40

answers:

1

Just imagine you have the following class

[DataContract]
public class NamedList
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public IList<string> Items { get; private set; }

    public DumpList(string name)
    {
        Name = name;
        Items = new List<string>();
    }
}

If you serialize this into a file, it is quite easy, cause the concrete class behind the IList is known and can be serialized.

But what happens if you try to deserialize this file back into memory?
It works without any direct error occuring.

The problem comes if you try to add or remove something from the list. In that case you'll get an exception. And the root of this exception comes from the case that the deserialized object uses as concrete implementation for the IList an Array.

To avoid this problem in this simple example is easy. Just serialize the concrete backing store instead of the public property and make the change in the constructor:

[DataMember(Name = "Items")]
private List<string> _Items;

public IList<string> Items
{
    get
    {
        return _Items;
    }
}

public DumpList(string name)
{
    Name = name;
    _Items = new List<string>();
}

But the more interesting question is:

  • Why chooses the Deserializer the Array type as concrete implementation of the IList interface?
  • Is it possible to change the settings which class should be taken for each interface?
  • If i have a self defined interface and several implementations of this interface, is it possible to tell the Deserializer which concrete class should be taken for a given interface?
+1  A: 

If you use the NetDataContractSerializer, which stores type information along with the serialized object, your problem should be solved. However, it does at the same time reduce interoperability to non-.NET clients.

Lucero
Actually i don't want to store type information within my xml file. But it seems that MS has implemented some mechanism to take a specific type if none is given (like an interface only). And the question is how do they resolve it and can you configure this mechanism in some way (maybe through an Attribute on my interface/class or by configuring the DataContractSerializer instance)
Oliver
The full docs for the Data Contract serialization behavior with collection types is here on MSDN: http://msdn.microsoft.com/en-us/library/aa347850.aspxReading that, I'm afraid that you cannot control the type instantiated for a collection interface.
Lucero
@Lucero: I did a rough read through the page you mentioned and found the sentence you mean: `the choice of type is built into WCF`. So this feels very uncomfortable. I let the question open for a while, maybe someone has another idea. But i think there won't be any better answer. *sigh*
Oliver
@Oliver, that's exactly what I mean. I also did some other research like looking into the code with Reflector, but that yielded no obvious way to deal with this either.Still, you could have a look at the output generated by the `NetDataContractSerializer`. If the only difference is added type information, you may be able to write an XSLT transform which converts the XML without type information to XML with type information as you need it for the `NetDataContractSeralizer` on the fly when loading the file. Kind of a hack, but it would let you choose the type explicitly in a generic way...
Lucero
Thanks for sharing your ideas.
Oliver