This site has been taken over by the staff of www.ASPDeveloper.Net

Please report errors to suggest@aspdeveloper.net

BizTalk Utilities CV ,   Jobs ,   Code library  
 
Home Page
XmlSerializer
Custom Serialization
IXmlSerializable
DataSet Object
Namespace at runtime
XmlSerializer Namespaces
Serialization Namespaces
Event notifications
Serializing Objects
any and anyAttribute
XmlAnyElement
Serializing XML nodes
Choice Model Groups
Generic XmlSerializer
Runtime Overrides
Runtime Customization
Customizing Xml Serialization
Advanced XmlSerializer
XmlSerializer Attributes
Runtime exceptions
Serializing Collection Classes
<< XML DOM
XQuery >>

By :Mark Wilson
I am the creator of TopXML. I am available for international and local (Australia) contracts. I am a Solution Architect/Business Analyst. I have worked in IT in several countries (NZ, Australia, South Africa, UK) building and training teams for government and very large non-governmental organizations. I am ex-Microsoft Consulting Services. I wrote the first book on Microsoft XML published in 2000 called XML Programming with VB and ASP. Most recently I have been building tools for the SEO industry. Ask me for a 37 point SEO health-checkup for your website.
First posted :03/24/2008
Times viewed :2265

 

Streaming Context States

Besides the SerializationInfo, GetObjectData() also receives a context object that provides a hint about the destination of the serialized object in the form of a StreamingContextStates value. With this piece of information an object can choose the representation that is most efficient for the environment where it will be deserialized. For example, if the object will be re-created in another process currently running on the same machine, the object can pass system-wide handles, to files for example, verbatim thus avoiding extra overhead re-opening the file. If the object is intended to be deserialized on another machine, where the handle is not valid, the object can store a UNC path the receiving application can access instead of the handle. Table 12.5 shows the possible values of the StreamingContextStates enumeration.

1.8            Table 12.3 The values of the StreamingContextStates enumeration identify the source or the destination of a serialized object. The values can be combined.

StreamingContextStates Value

Description

All

The serialized data has to be valid in all contexts.

Clone

The object graph is cloned and stays within the same process. The cloned graph has access to the same handles and unmanaged resources as the original graph.

CrossAppDomain

The source or the destination is in a different AppDomain.

CrossMachine

The source or destination is on a different computer. The serialized data must not be machine specific.

CrossProcess

The source or the destination is a different process on the same computer. Machine specific data is permitted.

File

The source or the destination is a file. The serialized data must not be transient, process or machine specific.

Other

The source or the destination is unknown.

Persistence

The source or the destination is a persisted store, e.g a database, files, or another form of storage. The serialized data must not be transient, process or machine specific.

Remoting

The source or the destination is accessed through remoting, but the location is unknown. The serialized data must not be transient, process or machine specific.

Deserializing Objects with ISerializable

When you looked at the definition of the ISerializable interface in the previous paragraph you might have scratched your head and wondered why it does not define a method to customize deserialization. What’s all the flexibility worth if we do not have the deserialization counterpart to GetObjectData()? If it’s not defined in the interface how does it work? These are valid questions. Their answer lies only in the semantics of an interface definition. There very much is a counterpart to the GetObjectData() method, but the .NET team chose to require it in the form of a constructor, rather than adding a SetObjectData() method to the interface. An interface cannot express this requirement, because it can only define method signatures, not class constructors. Implementating this functionality in a constructor helps avoiding issues related to multiple, possibly even concurrent, calls to an interface method. The downside of this design is that we cannot rely on the compiler to detect a missing deserialization constructor. Instead, we have to guard deserialization operations with an exception handler block to make sure ill designed objects will not crash our applications.

You may feel somewhat uneasy to expose a constructor that allows direct access to all members of the class. After all, this bypasses all encapsulation and control mechanisms you carefully set up through overloaded constructors. One step to protect ourselves from illegitimate use of this constructor is to always declare the deserialization constructor protected instead of public. At least protected access to the constructor prevents explicit use of this constructor to instantiate objects. The serialization framework is not affected by this access restriction because it calls the constructor through the reflection API.

The signature of the deserialization constructor is identical to the signature of the GetObjectData() method, it receives a SerializationInfo object and a StreamingContext object. The SerializationInfo object contains the same name-value pairs we added in GetObjectData().

This time the StreamingContext object, provides information about the origin of the serialized data, i.e. whether it came from a live object running on the same machine or if it was received over a network or from a file. Once again we can leverage this information to optimize the overall serialization process like we have already seen when we already seen when we discussed implementing GetObjectData().

Figure 12.1 The SerializationInfo object serves as a container for the data we want to serialize. We fill the container in the GetObjectData) method of the ISerializable interface. When the formatter deserializes the object it hands us the container to retrieve the data we put into it.

The following example class in listing 12.1 below shows how we can implement the ISerializable interface in order to persist a non-serializable SqlConnection object. We wrap the SqlConnection object with a SerializableSqlConnection class that implements ISerializable. The first choice to make a non-serializable SqlConnection would be to derive a new class that implements ISerializable, but unfortunately the SqlConnection connection class is sealed and can not be extended. When we wrap a class we have to implement pass-through methods for each public property and method of the class. We will learn a better technique than wrapping a class in section 12.3, but for now we take a look how we can implement ISerializable.

Our GetObjectData() implementation persists enough information to create a new SqlConnection object that connects to the same database as the serialized object. It calls the AddValue() method to add the connection string and the connection state to a SerializationInfo object. The formatter in use will write the two values to output stream. Later on, when we deserialize an object from the persisted data, the formatter will populate a SerializationInfo object with the name-value pairs the original object persisted in GetObjectData(). It passes the new SerializationInfo to the deserialization constructor. The constructor can retrieve the values by their name through a number of type-safe Get methods exposed by the SerializationInfo class. Table 12.6 shows the complete list of these Get methods.

20        Listing 12.1 This class serializes a SqlConnection object, which is not marked [Serializable]

using System;

using System.Runtime.Serialization; // for ISerializable

using System.Data.SqlClient; // for SqlConnection

using System.Data; // for ConnectionState

namespace Christoph.Simple

{

  [Serializable]                                         | #1

  public class SerializableSqlConnection : ISerializable  |

  {

    private SqlConnection _DbConnection;                       | #2

    protected SerializableSqlConnection (

      SerializationInfo info, StreamingContext context)        | #3

    {                                                          |

      try                                                      |

      {                                                        |

        string connectionString = info.GetString( "DbString" );|

        _DbConnection = new SqlConnection( connectionString ); |

        if( ConnectionState.Open                               |

          != (ConnectionState)info.GetValue("DbState",         |

            typeof(ConnectionState)) )                         |

        {                                                      |

          _DbConnection.Open();                                |

        }                                                      |

      }                                                        |

      catch( SerializationException ex )

      {

        Console.WriteLine("exception ex {0}", ex.Message );

        Console.WriteLine("exception ex {0}", ex.StackTrace );

      }

    } // SerializableSqlConnection

    public void GetObjectData(

      SerializationInfo info, StreamingContext context )            |#4

    {                                                               |

      if( null != _DbConnection )                                   |

      {                                                             |

        info.AddValue( "DbString", _DbConnection.ConnectionString );|

        info.AddValue( "DbState", _DbConnection.State );            |

      }                                                             |

    }  // GetObjectData                                             |

  

   // more useful code omitted …

 } // class PersistableSqlConnection

} // namespace

(annotation) <#1 Mark the class serializable and declare that it handles its own serialization.>

(annotation) <#2 The SqlConnection class is not serializable.>

(annotation) <#3 The deserialization constructor is called to restore all the serialized members. The constructor retrieves the stored values from SerializationInfo object to create a new SqlConnection object. If the original connection was open at the time it was serialized, the new connection is opened. We can declare the constructor protected to guard against explicit use.>

(annotation) <#4 The GetObjectData() method stores enough information to restore the SqlConnection.>

There is one more detail we have to know about in order to correctly implement a deserialization constructor. We must not execute any methods on any objects we retrieve from the SerializationInfo container. The .NET Framework does not guarantee that these objects are fully constructed and initialized when it is calling the deserialization constructor. In the example above, we can call Open() on the connection object only because we instantiated it ourselves, we did not retrieve it from the SerializationInfo.

1.9            Table 12.6 The SerializationInfo exposes methods to add and retrieve name-value pairs to describe an object.

Method

Description

public void AddValue(

  string name, XXX value

);

Adds a name-value pair to the SerializationInfo. Several overloads are available to add all types to the SerializationInfo

public bool GetBoolean(

  string name

);

Retrieves a Boolean value from the SerializationInfo.

public byte GetByte(

  string name

);

Retrieves an 8-bit unsigned integer value from the SerializationInfo.

public char GetChar(

  string name

);

Retrieves a Unicode character value from the SerializationInfo.

public DateTime GetDateTime(

  string name

);

Retrieves a DateTime value from the SerializationInfo.

public decimal GetDecimal(

  string name

);

Retrieves a Decimal value from the SerializationInfo.

public double GetDouble(

  string name

);

Retrieves a double-precision value from the SerializationInfo.

public SerializationInfoEnumerator GetEnumerator(

  string name

);

Returns an SerializationInfoEnumerator to iterate over the name-value pairs in the SerializationInfo.

public short GetInt16(

  string name

);

Retrieves a 16-bit signed integer value from the SerializationInfo.

public int GetInt32(

  string name

);

Retrieves a 32-bit signed integer value from the SerializationInfo.

public long GetInt64(

  string name

);

Retrieves a 64-bit signed integer value from the SerializationInfo.

public sbyte GetSByte(

  string name

);

Retrieves an 8-bit signed integer value from the SerializationInfo.

public float GetSingle(

  string name

);

Retrieves a single-precision value from the SerializationInfo.

public string GetString(

  string name

);

Retrieves a String value from the SerializationInfo.

public ushort GetUInt16(

  string name

);

Retrieves a 16-bit unsigned integer value from the SerializationInfo.

public uint GetUInt32(

  string name

);

Retrieves a 32-bit unsigned integer value from the SerializationInfo.

public ulong GetUInt64(

  string name

);

Retrieves a 64-bit unsigned integer value from the SerializationInfo.

public object GetValue(

  string name

);

Retrieves a value of any type from the SerializationInfo.

public void SetType(

  Type type

)

Sets the Type to appear in the serialized output. This type is instantiated when the object is deserialized.


Rate this article on a scale of 1 to 10

Your vote :  


 

Recent Jobs

Software Specialist, Linux - Finlan
Linux Core Technical Project Manage
Graphics designer at Tanzania. Expe
Integration Specialist Needed - Wor
Virtualization Server Infrastructur

View all Jobs (Add yours)
View all CV (Add yours)






    Email TopXML  

Front Page Daily Stuff TopXML Forum XML blogs XML Newsgroups BizTalk Biztalk Utilities Biztalk Utilities Tutorial B2B SAP XML Microsoft .NET Dotnet System XML Soapformatter SQLXML XMLserializer XQuery PHP PHP SimpleXML PHP XML Dom PHP XML RPC PHP XSLT Java Java Java XML Xalan Microsoft ASP ASP Schemas XML SQL Server XML XMLDom XSL XSL Tutorial XSLT Stylesheets General Javascript CSS XHTML WAP