WCF and abstract types

October 12th, 2009 by Andy Leave a reply »

This seems like a fairly straightforward issue to me, but after googling around I’m left wondering what I’m missing.

Suppose I have a web service that contains a Search() method that takes one of two possible types of query – a simple query or a complex query.   WCF doesn’t support xsd:choice, so I can’t use that, but it does support xsd:extension, so that should do the trick:

    [DataContract]
    [KnownType(typeof(SimpleQuery))]
    [KnownType(typeof(ComplexQuery))]
    class Query { }

    [DataContract]
    class SimpleQuery : Query { }

    [DataContract]
    class ComplexQuery : Query { }

    [ServiceContract]
    interface ISearchService
    {
        Results Search(Query query);
    }

This works ok, but it’s not quite right – the client can pass an instance of Query rather than SimpleQuery or ComplexQuery.   Query really needs to be abstract.   But does XML schema support that?   Yes, it does, through complextype’s abstract attribute.

So, problem solved.  We make Query abstract and WCF’s DataContractSerializer will add the abstract=”true” to the XSD it generates.  Except that it doesn’t.  It just ignores the fact that the Query class is abstract, which means that the client sees the class as non-abstract.  This means that the client can easily pass a Query instance to the server (which of course  causes the serializer on the server to blow up trying to create an instance of the abstract class).   Hmm.

So why doesn’t DataContractSerializer support abstract base classes?  It seems pretty simple, both in concept and implementation.   Presumably it’s deemed too OO-centric … but then why support inheritance (xsd:extension)?  

BTW There’s a StackOverflow question covering the same issue – like the poster I didn’t find any of the answers satisfactory.

Advertisement

Comments are closed.