Click here to Skip to main content
15,893,904 members
Articles / Desktop Programming / Windows Forms

Windows Services Made Simple

Rate me:
Please Sign up or sign in to vote.
4.62/5 (10 votes)
27 Jun 2007CPOL10 min read 94.5K   6.9K   69  
Describes how to build a Windows Service using the Pegasus Library.
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using Pegasus.Log4Net;

namespace Pegasus.Runtime.Serialization.Formatters.Xml
{
	/// <summary>
	/// Provides serialization to and from XML format.
	/// </summary>
	[Obsolete( "Use the XmlFormatter2 class in place of this class", false )]
	public class XmlFormatter : IFormatter
	{
        /// <summary>
        /// 
        /// </summary>
        public static ILog s_logger = LogManager.GetLogger( typeof( XmlFormatter ) );

		/// <summary>
		/// Initializes a new instance of the <see cref="T:XmlFormatter"/> class.
		/// </summary>
		public XmlFormatter()
		{
		}

		/// <summary>
		/// Gets or sets the <see cref="T:System.Runtime.Serialization.SerializationBinder"></see> that performs type lookups during deserialization.
		/// </summary>
		/// <value></value>
		/// <returns>The <see cref="T:System.Runtime.Serialization.SerializationBinder"></see> that performs type lookups during deserialization.</returns>
		public SerializationBinder Binder
		{
			get
			{
				throw new Exception( "The method or operation is not implemented." );
			}
			set
			{
				throw new Exception( "The method or operation is not implemented." );
			}
		}

		/// <summary>
		/// Gets or sets the <see cref="T:System.Runtime.Serialization.StreamingContext"></see> used for serialization and deserialization.
		/// </summary>
		/// <value></value>
		/// <returns>The <see cref="T:System.Runtime.Serialization.StreamingContext"></see> used for serialization and deserialization.</returns>
		public StreamingContext Context
		{
			get
			{
				throw new Exception( "The method or operation is not implemented." );
			}
			set
			{
				throw new Exception( "The method or operation is not implemented." );
			}
		}

		/// <summary>
		/// Gets or sets the <see cref="T:System.Runtime.Serialization.SurrogateSelector"></see> used by the current formatter.
		/// </summary>
		/// <value></value>
		/// <returns>The <see cref="T:System.Runtime.Serialization.SurrogateSelector"></see> used by this formatter.</returns>
		public ISurrogateSelector SurrogateSelector
		{
			get
			{
				throw new Exception( "The method or operation is not implemented." );
			}
			set
			{
				throw new Exception( "The method or operation is not implemented." );
			}
		}

		/// <summary>
		/// Serializes an object, or graph of objects with the given root to the provided stream.
		/// </summary>
		/// <param name="serializationStream">The stream where the formatter puts the serialized data. This stream can reference a variety of backing stores (such as files, network, memory, and so on).</param>
		/// <param name="graph">The object, or root of the object graph, to serialize. All child objects of this root object are automatically serialized.</param>
		public void Serialize( Stream serializationStream, object graph )
		{
			XmlWriterSettings settings = new XmlWriterSettings();
			settings.ConformanceLevel = ConformanceLevel.Document;
			settings.Encoding = UTF8Encoding.UTF8;
			settings.Indent = true;
			settings.OmitXmlDeclaration = true;

			XmlWriter xmlWriter = XmlWriter.Create( serializationStream, settings );

            try
            {
                // Build the security token
                xmlWriter.WriteStartDocument();

                WriteMember( xmlWriter, "ObjectGraph", graph );

                xmlWriter.WriteEndDocument();
                xmlWriter.Flush();
            }
            catch( Exception ex )
            {
                s_logger.Error( "Serialize failed", ex );
                throw;
            }
			finally
			{
				xmlWriter.Close();
			}
		}

		/// <summary>
		/// Deserializes the data on the provided stream and reconstitutes the graph of objects.
		/// </summary>
		/// <param name="serializationStream">The stream that contains the data to deserialize.</param>
		/// <returns>
		/// The top object of the deserialized graph.
		/// </returns>
		public object Deserialize( Stream serializationStream )
		{
			// TODO: Use a forward reader, it should be faster...

			XmlDocument xmlDoc = new XmlDocument();
			xmlDoc.Load( serializationStream );

			foreach( XmlNode node in xmlDoc.ChildNodes )
			{
				if( node.Name == "ObjectGraph" )
				{
					return ReadMember( node );
				}
			}

			return null;
		}

		/// <summary>
		/// Writes the member.
		/// </summary>
		/// <param name="xmlWriter">The XML writer.</param>
		/// <param name="memberName">Name of the member.</param>
		/// <param name="data">The data.</param>
		private void WriteMember( XmlWriter xmlWriter, string memberName, object data )
		{
			if( data == null )
			{
				WriteObjectRef( xmlWriter, data, memberName, typeof( object ) );
			}
			else
			{
				Type type = data.GetType();
				if( type == typeof( bool ) ||
					type == typeof( char ) ||
					type == typeof( sbyte ) ||
					type == typeof( byte ) ||
					type == typeof( short ) ||
					type == typeof( ushort ) ||
					type == typeof( int ) ||
					type == typeof( uint ) ||
					type == typeof( long ) ||
					type == typeof( ulong ) ||
					type == typeof( float ) ||
					type == typeof( double ) ||
					type == typeof( decimal ) )
				{
					WriteBasicType( xmlWriter, data, memberName );
				}
				else if( type == typeof( DateTime ) )
				{
					WriteBasicType( xmlWriter, Convert.ToDateTime( data, CultureInfo.InvariantCulture ), memberName );
				}
				else if( type.IsArray )
				{
					this.WriteArray( xmlWriter, data, memberName, type );
				}
				else if( type.IsValueType )
				{
					this.WriteValueType( xmlWriter, data, memberName, type );
				}
				else
				{
					this.WriteObjectRef( xmlWriter, data, memberName, type );
				}
			}
		}

		/// <summary>
		/// Writes the type of the basic.
		/// </summary>
		/// <param name="xmlWriter">The XML writer.</param>
		/// <param name="val">The val.</param>
		/// <param name="name">The name.</param>
		private void WriteBasicType( XmlWriter xmlWriter, object val, string name )
		{
			xmlWriter.WriteStartElement( XmlConvert.EncodeName( name ) );
			xmlWriter.WriteAttributeString( "Type", val.GetType().AssemblyQualifiedName );

			xmlWriter.WriteValue( val.ToString() );

			xmlWriter.WriteEndElement();
		}

		/// <summary>
		/// Writes the array.
		/// </summary>
		/// <param name="xmlWriter">The XML writer.</param>
		/// <param name="obj">The obj.</param>
		/// <param name="name">The name.</param>
		/// <param name="memberType">Type of the member.</param>
		private void WriteArray( XmlWriter xmlWriter, object obj, string name, Type memberType )
		{
			xmlWriter.WriteStartElement(  XmlConvert.EncodeName( name ) );
			xmlWriter.WriteAttributeString( "Type", memberType.AssemblyQualifiedName );

			// Write the elements of the array
			Array array = (Array) obj;
			foreach( object element in array )
			{
				WriteMember( xmlWriter, name, element );
			}

			xmlWriter.WriteEndElement();
		}

		/// <summary>
		/// Writes the type of the value.
		/// </summary>
		/// <param name="xmlWriter">The XML writer.</param>
		/// <param name="obj">The obj.</param>
		/// <param name="name">The name.</param>
		/// <param name="memberType">Type of the member.</param>
		private void WriteValueType( XmlWriter xmlWriter, object obj, string name, Type memberType )
		{
			xmlWriter.WriteStartElement( XmlConvert.EncodeName( name ) );
			xmlWriter.WriteAttributeString( "Type", memberType.AssemblyQualifiedName );

			FieldInfo[] fields = memberType.GetFields( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
			object[] membersData = FormatterServices.GetObjectData( obj, fields );

			int count = fields.Length;
			for( int x = 0; x < count; x++ )
			{
				WriteMember( xmlWriter, fields[ x ].Name, membersData[ x ] );
			}

			xmlWriter.WriteEndElement();
		}

		/// <summary>
		/// Writes the object ref.
		/// </summary>
		/// <param name="xmlWriter">The XML writer.</param>
		/// <param name="obj">The obj.</param>
		/// <param name="name">The name.</param>
		/// <param name="memberType">Type of the member.</param>
		private void WriteObjectRef( XmlWriter xmlWriter, object obj, string name, Type memberType )
		{
			xmlWriter.WriteStartElement( XmlConvert.EncodeName( name ) );
			xmlWriter.WriteAttributeString( "Type", memberType.AssemblyQualifiedName );

			if( obj != null )
			{
				if( memberType != typeof( string ) )
				{
					MemberInfo[] members = FormatterServices.GetSerializableMembers( memberType );
					object[] membersData = FormatterServices.GetObjectData( obj, members );

					int count = members.Length;
					for( int x = 0; x < count; x++ )
					{
						WriteMember( xmlWriter, members[ x ].Name, membersData[ x ] );
					}
				}
				else
				{
					xmlWriter.WriteValue( (string) obj );
				}
			}
			else
			{
				xmlWriter.WriteValue( "NULL" );
			}

			xmlWriter.WriteEndElement();
		}

		/// <summary>
		/// Reads the member.
		/// </summary>
		/// <param name="node">The node.</param>
		/// <returns></returns>
		private object ReadMember( XmlNode node )
		{
			object ret = null;

			XmlAttribute attrib = node.Attributes[ "Type" ];
			if( attrib == null )
			{
				throw new XmlException( string.Format( "Missing 'Type' attribute on node {0}", node.Name ) );
			}

			string qualifiedAssemblyName = attrib.Value;

			Type memberType = Type.GetType( qualifiedAssemblyName );
			if( memberType == null )
			{
				throw new XmlException( string.Format( "Unknown 'Type' attribute {0} on node {1}", qualifiedAssemblyName, node.Name ) );
			}

			if( memberType == typeof( bool ) )
			{
				ret = Convert.ToBoolean( node.InnerText );
			}
			else if( memberType == typeof( char ) )
			{
				ret = Convert.ToChar( node.InnerText );
			}
			else if( memberType == typeof( string ) )
			{
				ret = node.InnerText;
			}
			else if( memberType == typeof( sbyte ) )
			{
				ret = Convert.ToSByte( node.InnerText );
			}
			else if( memberType == typeof( byte ) )
			{
				ret = Convert.ToByte( node.InnerText );
			}
			else if( memberType == typeof( short ) )
			{
				ret = Convert.ToInt16( node.InnerText );
			}
			else if( memberType == typeof( ushort ) )
			{
				ret = Convert.ToUInt16( node.InnerText );
			}
			else if( memberType == typeof( int ) )
			{
				ret = Convert.ToInt32( node.InnerText );
			}
			else if( memberType == typeof( uint ) )
			{
				ret = Convert.ToUInt32( node.InnerText );
			}
			else if( memberType == typeof( long ) )
			{
				ret = Convert.ToInt64( node.InnerText );
			}
			else if( memberType == typeof( ulong ) )
			{
				ret = Convert.ToUInt64( node.InnerText );
			}
			else if( memberType == typeof( float ) )
			{
				ret = Convert.ToSingle( node.InnerText );
			}
			else if( memberType == typeof( double ) )
			{
				ret = Convert.ToDouble( node.InnerText );
			}
			else if( memberType == typeof( decimal ) )
			{
				ret = Convert.ToDecimal( node.InnerText );
			}
			else if( memberType == typeof( DateTime ) )
			{
				ret = Convert.ToDateTime( node.InnerText, CultureInfo.InvariantCulture );
			}
			else if( memberType.IsArray )
			{
				ReadArray( node, ref ret, memberType );
			}
			else if( memberType.IsValueType )
			{
				ReadValueType( node, ref ret, memberType );
			}
			else
			{
				ReadObjectRef( node, ref ret, memberType );
			}

			return ret;
		}

		/// <summary>
		/// Reads the array.
		/// </summary>
		/// <param name="node">The node.</param>
		/// <param name="theObject">The object.</param>
		/// <param name="memberType">Type of the member.</param>
		private void ReadArray( XmlNode node, ref object theObject, Type memberType )
		{
			int count = node.ChildNodes.Count;

			// Create the array object
			Array array = Array.CreateInstance( memberType.GetElementType(), count );
			
			// Read each the element of the array
			for( int x = 0; x < count; x++ )
			{
				array.SetValue( ReadMember( node.ChildNodes[ x ] ), x );
			}

			theObject = array;
		}

		/// <summary>
		/// Reads the type of the value.
		/// </summary>
		/// <param name="node">The node.</param>
		/// <param name="theObject">The object.</param>
		/// <param name="memberType">Type of the member.</param>
		private void ReadValueType( XmlNode node, ref object theObject, Type memberType )
		{
			theObject = FormatterServices.GetSafeUninitializedObject( memberType );
			FieldInfo[] fields = memberType.GetFields( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );

			int count = fields.Length;
			object[] data = new object[ count ];

			for( int x = 0; x < count; x++ )
			{
				string name = fields[ x ].Name;
				XmlNode childNode = node.SelectSingleNode( XmlConvert.EncodeName( name ) );
				if( childNode != null )
				{
					data[ x ] = ReadMember( childNode );
				}
			}

			theObject = FormatterServices.PopulateObjectMembers( theObject, fields, data );
		}

		/// <summary>
		/// Reads the object ref.
		/// </summary>
		/// <param name="node">The node.</param>
		/// <param name="theObject">The object.</param>
		/// <param name="memberType">Type of the member.</param>
		private void ReadObjectRef( XmlNode node, ref object theObject, Type memberType )
		{

			if( node.InnerText != "NULL" )
			{
				if( memberType == typeof( string ) )
				{
					theObject = node.InnerText;
				}
				else
				{
					theObject = FormatterServices.GetSafeUninitializedObject( memberType );
					MemberInfo[] members = FormatterServices.GetSerializableMembers( memberType );

					int count = members.Length;
					object[] data = new object[ count ];

					for( int x = 0; x < count; x++ )
					{
						string name = members[ x ].Name;
						XmlNode childNode = node.SelectSingleNode( XmlConvert.EncodeName( name ) );
						if( childNode != null )
						{
							data[ x ] = ReadMember( childNode );
						}
					}

					theObject = FormatterServices.PopulateObjectMembers( theObject, members, data );
				}
			}
			else
			{
				theObject = null;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions