2009-02-14

WCF – serialize the unserializable

Introduction

WCF serialization rely on the Data Contract and Data Member decoration

This post discuss one simple trick that available in cases that you having your own data contract that holding data members that does not been decorated for the WCF serialization

This trick will work as long as you reuse the same assembly of the data contract both on the client and service sides

There some other techniques for advance serialization which will beyond the scope of this post

you can find the post code in here

Our Test Case

In our test case we will have data contract that has data member of type DataTable

Note: you do not need this trick for typed data table, it does serialized well

Having the following service:

[ServiceContract]
public interface IMyService
{
[OperationContract]
CustomEntity GetData ();
}

[DataContract]
public class CustomEntity
{
[DataMember]
public DataTable Table { get; set; }
}

Notice that we try to have data contract that having data member which does not design to be serialized using WCF serialization (because DataTable does not decorate with data contract attribute)

The trick is very simple and it can be assign for any similar cases
it simply using the data contract serialization processing with little twist

We will serialize the DataTable indirectly using private data member which won’t expose by our Custom Entity API so the consumer of our Custom Entity won’t e aware of it, still the WCF will use it during the serialization process

Steps needed to achieve our goal

  1. Remove the data member decoration from the Table property
  2. Add custom private data member that will handle the serialization process
    1. We need one member to serialize the DataTable schema
    2. And other member to serialize the DataTable data (the data deserialization must occur after the schema deserialization completed)

Our data contract should look like the following one

[DataContract]
public class CustomEntity
{
[DataMember (Order=0)]
private byte[] TableSchemaSerialization
{
get
{
// the folowing operation will occur during the WCF serializing
var srm = new MemoryStream ();
this.Table.WriteXmlSchema (srm);
return srm.ToArray ();
}
set
{
// the folowing operation will occur during the WCF deserializing
this.Table = new DataTable ();
var srm = new MemoryStream (value);
this.Table.ReadXmlSchema (srm);
}
}

[DataMember (Order=1)]
private byte[] TableDataSerialization
{
get
{
// the folowing operation will occur during the WCF serializing
var srm = new MemoryStream ();
this.Table.WriteXml (srm);
return srm.ToArray ();
}
set
{
// the folowing operation will occur during the WCF deserializing
var srm = new MemoryStream (value);
this.Table.ReadXml (srm);
}
}

//[DataMember]
public DataTable Table { get; set; }
}

Conclusion

As long as we reusing the data contract at both service and client sides

We can build our data contract to intercept the serialization process without changing the data contract API

No comments: