title: Deserialize derived types in WCF service as base types but retain type information
body: <p>I want my service to be able to accept and return types derived from <code>BaseType</code> without actually knowing what those types will be.  I have almost got a solution using a custom <code>DataContractResolver</code> based on the <a href="http://blogs.msdn.com/b/youssefm/archive/2009/06/05/introducing-a-new-datacontractserializer-feature-the-datacontractresolver.aspx">SharedTypeResolver from this excellent blog post</a>.  </p>
  
  <p>The missing piece of the puzzle is that the types my service will handle might not be shared and known to the service but I still want to accept them and be aware of what the type should have been.  I have come up with the following example of a service that acts as a stack.  You can push and pop any type derived from <code>BaseType</code> provided you use the <code>SharedTypeResolver</code> and the types are shared between client and server.</p>
  
  <pre><code>[DataContract]
  public class BaseType
  {
      [DataMember]
      public string SomeText { get; set; }
  
      public override string ToString()
      {
          return this.GetType().Name + ": " + this.SomeText;
      }
  }
  
  [DataContract]
  public class DerivedType : BaseType
  {
      [DataMember]
      public int SomeNumber { get; set; }
  
      public override string ToString()
      {
          return base.ToString() + ", " + this.SomeNumber;
      }
  }
  
  [ServiceContract]
  public interface ITypeStack
  {
      [OperationContract]
      void Push(BaseType item);
  
      [OperationContract]
      BaseType Pop();
  }
  
  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
  public class TypeStackService : ITypeStack
  {
      private Stack&lt;BaseType&gt; stack = new Stack&lt;BaseType&gt;();
  
      public void Push(BaseType item)
      {
          this.stack.Push(item);
      }
  
      public BaseType Pop()
      {
          return this.stack.Pop();
      }
  }
  </code></pre>
  
  <p>This is obviously greatly a simplified example of the problem I'm having.  A client can quite merrily push and pop <code>BaseType</code> or <code>DerivedType</code> because both client and server know about them, but if the client pushes <code>UnsharedType</code> which the service does not know I get an error as you would expect.</p>
  
  <blockquote>
    <p>The formatter threw an exception while trying to deserialize the
    message: There was an error while trying to deserialize parameter
    <a href="http://tempuri.org/:item">http://tempuri.org/:item</a>. The InnerException message was 'Error in
    line 1 position 316. Element '<a href="http://tempuri.org/:item">http://tempuri.org/:item</a>' contains data
    from a type that maps to the name 'TestWcfClient, Version=1.0.0.0,
    Culture=neutral, PublicKeyToken=null:TestWcfClient.UnsharedType'. The
    deserializer has no knowledge of any type that maps to this name.
    Consider changing the implementation of the ResolveName method on your
    DataContractResolver to return a non-null value for name
    'TestWcfClient.UnsharedType' and namespace 'TestWcfClient,
    Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.'.  Please see
    InnerException for more details.</p>
  </blockquote>
  
  <p>My current thinking is to add <code>IExtensibleDataObject</code> to <code>BaseType</code> to hold the values from an unshared type and make an unshared type look like <code>BaseType</code> to the service on deserialization when an item is pushed; the opposite would need to happen when an item is popped.  I'm just not sure how to go about it.  My thoughts so far on possible approaches:</p>
  
  <ul>
  <li>Further customisation to <code>DataContractResolver</code> which might involve a <code>TypeDelegator</code></li>
  <li>Using <code>IDataContractSurrogate</code> in place of an unshared type</li>
  <li>Somehow retain the serialized XML the service received when an item is pushed, then use this in the reply when an item is popped</li>
  <li>Using a message inspector to manipulate the messages</li>
  </ul>
  
  <p>I've no idea if any of these will work, what would be involved or what is the best solution.  Do you?</p>