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 = "https://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.
- The data member on the client is set to 5.
- OnSerializing is called and changes the data member from 5 to 4.
- 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.
- The service is called.
- The service initializes the type to its default value, which for the data member is 0.
- OnDeserializing is called and changes the data member from 0 to 2.
- 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.
- OnDeserialized is called and changes the data member from 4 to 1.
- The service method is called and sees the value of the data member as 1.
Next time: Keeping up with Extension Versions