To gain even more control over the serialization process, you can implement the ISerializable interface and a special constructor: [SerializableAttribute] class MyData : ISerializable { string s = "Wahoo!"; int n = 6; public string String { get { return s; } set { value = s; n = s.Length; } } public int Length { get { return n; } } public MyData() {} #region Implementation of ISerializable public MyData( SerializationInfo info, StreamingContext context) { // Get value from name/value pairs s = info.GetString("MyString"); // Cache the string's length n = s.Length; } public void GetObjectData( SerializationInfo info, StreamingContext context) { // Add value to name/value pairs info.AddValue("MyString", s); } #endregion } Implementing ISerializable.GetObjectData puts your class on the hook to populate the name/value pairs that the formatter is using to fill the stream during serialization. GetObjectData is provided with two pieces of information: a place to put the fields to serialize (called the serialization information ) and the location where the object is going (called the context state ). GetObjectData must add all the fields to the serialization information that it would like to have serialized, naming each one. The formatter uses these names to write the data: <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <a1:Form1_x002B_MyData id="ref-1" ...> < MyString id="ref-3">Wahoo!</s> </a1:Form1_x002B_MyData> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Deserialization happens with the special constructor, which also takes serialization info and a context state, this time to pull out the data. The SerializationInfo class provides several methods for pulling out typed data. For built-in types, you can use the specific method, such as GetString. For general types, you can use the GetValue method. For example, the following two lines of code are equivalent, with the latter the only choice for custom types: s = info.GetString("MyString"); s = (string)info.GetValue("MyString", typeof(string)); |