views:

561

answers:

1

I can't make this scenario work. Here's the pattern-

[DataContract]
/*abstract*/ class BaseT
{ ... }

[DataContract]
class ChildT : BaseT
{ ... }

[DataContract]
class MessageContents
{
    [DataMember]
    public BaseT[] XX; // Array of BaseT objects. I need WCF to somehow figure out that they're actually ChildT.
}

// ...receive a webHttp request of type MessageContents...

// cast to use MessageContents.XX as a ChildT[] instead of a BaseT[]
ConcreteClass[] QQ = (ConcreteClass[])request.xx;

I've tried annotating practically everything with KnownType or KnownServiceType to no avail.

If I make BaseT abstract, I get a deserialization error 'cannot instance abstract class'. If I make BaseT concrete, I don't get a deserialization error. Instead, when I go to cast it to ChildT, I'm getting "unable to cast object of type 'BaseT[]' to type 'ChildT[]'".

+1  A: 

If you have the BaseT object definition tagged with KnownType and list ChildT there, it will work fine with the abstract base (I do this all the time). Your problem is that array covariance isn't allowed in C#, so you can't cast BaseT[] to ChildT[]. Casting the individual elements to ChildT will work, though- you can see this if you inspect the array in the debugger- if you need a ChildT[] let LINQ do the work for you (eg, baseArray.Cast().ToArray()).

nitzmahone
God I love this site. Brilliant, thank you very much.
Alex Forster