Collections, [DataContract] and svcutil

I'm trying to understand the best way to pass strongly-typed collections
between an Indigo service and client. I have the following test DataContract:

[DataContract]
public class Book
{
[DataMember]
public string Title;
[DataMember]
public string ISBN;
}

[DataContract]
[KnownType(typeof(Book))]
public class LibraryCatalog
{
[DataMember]
public string CatalogName;
[DataMember]
public Book[] Books;
[DataMember]
public List<Book> Books2;
[DataMember]
public IList<Book> Books3;
[DataMember]
public Hashtable Books4;
[DataMember]
public IDictionary Books5;
[DataMember]
public Dictionary<string, Book> Books6;
[DataMember]
public IDictionary<string, Book> Books7;
}

Using the September 2005 CTP toolset and svcutil, the generated proxy class
contains the following (my comments added):

// makes sense
private IndigoCollectionsTestServer.Book[] BooksField;

// works, but why isn't this a List<Book>?
private IndigoCollectionsTestServer.Book[] Books2Field;

// this is what I really want to use. Why is it only an object?
private object Books3Field;

// Make sense -- requires [KnownType(typeof(Book))] so client can cast
// types appropriately. I wonder why it's not an actual Hashtable
object?
private System.Collections.Generic.Dictionary<object, object>
Books4Field;

// Why isn't this an IDictionary object?
private object Books5Field;

// Makes sense. This is what I'd expect.
private System.Collections.Generic.Dictionary<string,
IndigoCollectionsTestServer.Book> Books6Field;

// Why isn't this like Books6, only with IDictionary<>?
private object Books7Field;

private string CatalogNameField;

Questions:
1) What's going on in the example above? Why are some strong types carried
through and not others? Is this because of bugs in the current tools, or is
this the intendend, documented behavior?

2) What best practices are you folks using to get strongly-typed collections
on both sides?

3) Is there [DataContract] documentation on how proxies are generated so I
don't have to resort to trial-and-error?

4) I'm using [DataContract] so that I can have good support for versioning
as the clients and service evolve independently. In my understanding, using
ISerializable or [Serializable] isn't a best practice for versioning. Is
this right?

5) Is any of the above related to a choice of serializer (XmlFormatter or
XmlSerializer)? XmlFormatter is preferred, from what I read.

TIA,
Galen
Galen Earl Murdock
Principal Software Developer
Veracity Solutions, Inc.

[2828 byte] By [GalenMurdock] at [2008-2-6]
# 1
Hi Galen

i can't answer to all your questions, unless i investigate your code.. and unfortunately i'm out of time, but i'll try to give some help.

You have to think on the wire. On the wire Books and Books2 are exactly the same. If you create the schema for LibraryCatalog you'll check two things:

- Books and Books2 are ArrayOfBooks
- You can't serialize interfaces or IDictionaries.

I'm not inside the details of how indigo allows the serialization of IDictionary, but I'm sure it must go around xml types, and use XmlAny. Have you tried to explicity use Xml types ?

You should investigate the resulted schema from your data contract. I'm sure that checking it would reveal most of your questions.

A way to go around this, would be to use ChannelFactory instead of generated proxies. If you share the Data Contract with the service client, you can create the channel in runtime and don't base the creation on an incomplete schema.

hope it helps
regards

HugoBatista at 2007-9-9 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 2

1. They are not bugs. You can use interfaces (IList, etc.) in your DataContract, but we emit them as xsd:anyType, which when import gets turned into System.Object. This behavior is by design. Why? The short answer is that because CLR interfaces support multiple inhieritance and XSD can't really represent that -- it least in a fashion that would be interoperable.

2. Don't use interfaces.

3. I think that we have some docs in the SDK. EugeneOs was working on a XSD -> DataContact doc that I think is going in. You can ping him at eugeneos@microsoft.com.

4. New types shouldn't use [Serializable] -- we support it for legacy reasons.

5. The rules between the XmlSerializer and XmlFormatter are completely different -- save for the way that we handle IXmlSerializable.

douglasp at 2007-9-9 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 3

We currently support only actual collection types, not collection interfaces. In addition to Doug's point about multiple inheritance, this is because, for example, not everything implementing IEnumerable is serializable (what if it doesn’t have a default constructor, of has no Add method?) We are considering changing this behavior after Beta2 (and if an invalid collection is “plugged in”, we could throw.)

Roundtripping actual CLR types is not the intent of the data contract model. Different types can appear on the service and on the client, as long as they have the same data contract. For example, Book[] and List<Book> have the same data contract (same schema and wire representation).

To customize the collection types you get on the proxy, use the /rct switch on svcutil.exe

EugeneOsovetsky at 2007-9-9 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...

Visual Studio Orcas

Site Classified