Serialization and Types


How does a DataContract type get initialized on the server? When I change the constructor for the type, nothing happens.

Older serializers relied on calling the parameter-less constructor to initialize the type when deserializing data. Data contract types have all of the data members initialized to the default values without a constructor being called. However, you can still introduce callback hooks into the serialization process by decorating methods on your data contract type with attributes. Here's a sample program that shows you exactly what goes on.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;

[DataContract]
public class Data
{
[DataMember]
public int a;

[OnDeserialized]
void OnDeserialized(StreamingContext c)
{
Console.WriteLine("OnDeserialized: {0}", a);
a = 1;
}

[OnDeserializing]
void OnDeserializing(StreamingContext c)
{
Console.WriteLine("OnDeserializing: {0}", a);
a = 2;
}

[OnSerialized]
void OnSerialized(StreamingContext c)
{
Console.WriteLine("OnSerialized: {0}", a);
a = 3;
}

[OnSerializing]
void OnSerializing(StreamingContext c)
{
Console.WriteLine("OnSerializing: {0}", a);
a = 4;
}
}

[ServiceContract]
public interface IService
{
[OperationContract]
void Method(Data d);
}

public class Service : IService
{
public void Method(Data d)
{
Console.WriteLine("Method: {0}", d.a);
}
}

class Program
{
static void Main(string[] args)
{
string address = "http://localhost:8000/";
Binding binding = new BasicHttpBinding();
ServiceHost host = new ServiceHost(typeof(Service));
host.AddServiceEndpoint(typeof(IService), binding, address);
host.Open();
ChannelFactory<IService> factory = new ChannelFactory<IService>(binding);
factory.Open();
IService proxy = factory.CreateChannel(new EndpointAddress(address));
Data d = new Data();
d.a = 5;
proxy.Method(d);
factory.Close();
host.Close();
Console.ReadLine();
}
}

You can try running the program to see the value of the data member at various points in time. If you're still confused, here's exactly what's going on.

  1. The data member on the client is set to 5.
  2. OnSerializing is called and changes the data member from 5 to 4.
  3. OnSerialized is called and changes the data member from 4 to 3. The service doesn't see this because the data has already been serialized. This only changed the value of the data member on the client.
  4. The service is called.
  5. The service initializes the type to its default value, which for the data member is 0.
  6. OnDeserializing is called and changes the data member from 0 to 2.
  7. Deserialization actually occurs and replaces the current value of the data members with the value sent by the client. This means that the data member has changed from 2 back to 4.
  8. OnDeserialized is called and changes the data member from 4 to 1.
  9. The service method is called and sees the value of the data member as 1.

Next time: Keeping up with Extension Versions

Comments (6)
  1. Rob says:

    How does the data contract get instantiated without a constructor being called?

  2. Message replay is an attack where a message is presented to a processor more than once in the hopes of

  3. Nen says:

    Very intresting, what i dont understand is why is the service instansitated until and unless the OnSerialized method is completed, shouldn’t the value from the client be passed after the  OnSerialized method is completed.

  4. Hi Nen,

    You’re actually correct.  The service is not instantiated until OnSerialized returns.  I didn’t notice that I had those out of order when I drafted the list.

Comments are closed.

Skip to main content