Click here to Skip to main content
15,894,460 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.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Soap;
using System.Xml.Serialization;

namespace Pegasus.Runtime.Serialization
{
	/// <summary>
	/// Summary description for DataMapper.
	/// </summary>
	[Obsolete( "Use SqlObjectMapper in place of this class.", false )]
	public class DataMapper
	{
		/// <summary>
		/// Hide the constructor.
		/// </summary>
		private DataMapper()
		{
		}
		
		private static Hashtable serializerCache = new Hashtable( 10 );
		private static XmlRootAttribute xRoot = new XmlRootAttribute( "MyVery_CustomRoot" );


		/// <summary>
		/// Map the data in the source object to a new instance of the destination object.
		/// </summary>
		/// <param name="source">Instance of the data object to be coppied</param>
		/// <param name="destination">An instance of object to be returned</param>
		/// <returns>An new instance of the destination object containing the data valued from the source</returns>
		static public object MapIt( object source, object destination )
		{
			//Type sourceType = (source is Type) ? (Type)source : source.GetType();
			Type destinationType = (destination is Type) ? (Type)destination : destination.GetType();

			return MapIt( source, destinationType );
		}
		
		private static XmlSerializer GetUniqueSerializerFromCache( Type type )
		{
			XmlSerializer serializer = null;
			if ( serializerCache.ContainsKey( type ) )
			{
				serializer = serializerCache[ type ] as XmlSerializer;
			}
			else
			{
				serializer = new XmlSerializer( type, xRoot );
				serializerCache[ type ] = serializer;
			}
			
			return serializer;
		}


		/// <summary>
		/// Map the data in the source object to a new instance of the destination object.
		/// </summary>
		/// <param name="source">Instance of the data object to be coppied</param>
		/// <param name="destinationType">The type of object to be returned</param>
		/// <returns>An new instance of the destination object containing the data valued from the source</returns>
		static public object MapIt( object source, Type destinationType )
		{

			// Create the Serializer for each of the objects
			XmlSerializer sourceSerializer = GetUniqueSerializerFromCache( source.GetType() );
			XmlSerializer destinationSerializer = GetUniqueSerializerFromCache( destinationType );
			

			// Get the namespaces for each of the objects
			string sourceNamespace = GetNamespace( source );
			string destinationNamespace = GetNamespace( destinationType );

			// Serialize the object and render into a string
			MemoryStream stream = new MemoryStream();
			sourceSerializer.Serialize( stream, source );
			stream.Seek( 0, SeekOrigin.Begin );
			string data = new StreamReader(stream).ReadToEnd();
			
			

			// Replace the namespace declaration in the xml from one object to the other 
			string changed = data;
			if( sourceNamespace != null )
			{
				changed = data.Replace( string.Format(@" xmlns=""{0}"">", sourceNamespace), string.Format(@" xmlns=""{0}"">", destinationNamespace) );
			}

			// Re-constitute the object from the modified XML String
			StringReader sreader = new StringReader( changed );
			object obj = destinationSerializer.Deserialize( sreader );		// instanciate the object
	
			// close the streams
			stream.Close();
			sreader.Close();
			
			return obj;
		}


		/// <summary>
		/// Get the XmlType attribute's namespace
		/// </summary>
		/// <param name="obj">Instance of the object or type of object</param>
		/// <returns>string value of the namespace specified in the XmlType's Namespace property</returns>
		private static string GetNamespace( object obj )
		{
			Type type = (obj is Type) ? (Type)obj : obj.GetType();
			foreach( object attribute in type.GetCustomAttributes(true) )
			{
				if( attribute is XmlTypeAttribute )
				{
					return ((XmlTypeAttribute)attribute).Namespace;
				}
			}

			return null;
		}

		/// <summary>
		/// Map the data in the source object to a new instance of the destination object.
		/// </summary>
		/// <param name="source">Instance of the data object to be coppied</param>
		/// <param name="destinationType">The type of object to be returned</param>
		/// <returns>An new instance of the destination object containing the data valued from the source</returns>
		static public object MapIt_Soap( object source, Type destinationType )
		{
			MemoryStream stream = null;
			
			try
			{
				// Create the Soap Formatter
				SoapFormatter sourceFormatter = new SoapFormatter();


				DumpAttributes( source );
				DumpAttributes( destinationType );


				// Serialize the object and render into a string
				stream = new MemoryStream();
				sourceFormatter.Serialize( stream, source );

				// Capture the string generated be the soap formatter's serialize
				stream.Seek( 0, SeekOrigin.Begin );
				string data = new StreamReader(stream).ReadToEnd();

				// Re-constitute the object from the modified XML String
				stream.Seek( 0, SeekOrigin.Begin );
				sourceFormatter.Binder = new MyBinder();
				sourceFormatter.Binder.BindToType( destinationType.Assembly.FullName, destinationType.FullName );
				object obj = sourceFormatter.Deserialize( stream );
				return obj;
			}
			catch( Exception ex )
			{
				Debug.WriteLine( ex );
				throw;
			}
			finally
			{
				if ( stream != null )
				{
					stream.Close();
				}
			}
		}


		/// <summary>
		/// Dump the Attribute to the debug output screen
		/// </summary>
		private static void DumpAttributes( object obj )
		{
			Type type = (obj is Type) ? (Type)obj : obj.GetType();
			Debug.WriteLine( string.Format( "Attributes for {0}", obj ) );
			foreach( object attribute in type.GetCustomAttributes(true) )
			{
				Debug.WriteLine( string.Format( "    {0}", attribute ) );
			}
		}


		/// <summary>
		/// An attempt a a
		/// </summary>
		sealed private class MyBinder : System.Runtime.Serialization.SerializationBinder
		{
			public override Type BindToType( string assemblyName, string typeName )
			{
				// The following line of code returns the type.
				Type typeToDeserialize = Type.GetType( string.Format("{0}, {1}", typeName, assemblyName) );

				return typeToDeserialize;
			}

		}


		/// <summary>
		/// Map the data in the source object to a new instance of the destination object using reflection
		/// </summary>
		/// <param name="source">Instance of the data object to be coppied</param>
		/// <param name="destinationType">The type of object to be returned</param>
		/// <returns>An new instance of the destination object containing the data valued from the source</returns>
		static public object MapIt_Reflection( object source, Type destinationType )
		{
			if( source == null )
			{
				return null;
			}

			// find the default constructor
			ConstructorInfo constructorDefault = destinationType.GetConstructor( new Type[0] );
			if( constructorDefault == null )
			{ 
				// find the constructor taking a string argument
				ConstructorInfo constructorTakingString = destinationType.GetConstructor( new Type[]{ typeof(string) } );
				if( constructorTakingString == null )
					return null;
				else
					return constructorTakingString.Invoke( new string[]{ source.ToString() } );
			}

			// Do the actual work now
			try
			{
				object destination = constructorDefault.Invoke( new object[0] );
				
				// Reflect all fileds to the new object
				ReflectFields( source, destination );

				// Reflect all properties to the new object
				ReflectProperties( source, destination );

				return destination;
			}
			catch( Exception ex )
			{
				Debug.WriteLine( ex );
				throw;
			}
		}

		/// <summary>
		/// Maps the it_ enum.
		/// </summary>
		/// <param name="source">The source.</param>
		/// <param name="destination">The destination.</param>
		/// <returns></returns>
		static	public	object	MapIt_Enum(
			object	source,
			object	destination
			)
		{
			//subDesc.Duration = (MFN.WebServices.Data.ECommerceData.Subscription.DurationEnum)Enum.Parse( typeof( MFN.WebServices.Data.ECommerceData.Subscription.DurationEnum ), subscriptionPricing.Duration.ToString(), true );
			
			return( Enum.Parse( destination.GetType(), source.ToString(), true ) );
		}


		/// <summary>
		/// Map the data in the source object to a new instance of the destination object using reflection
		/// </summary>
		/// <param name="source">Instance of the data object to be coppied</param>
		/// <param name="destination">The type of object to be returned</param>
		/// <returns>An new instance of the destination object containing the data valued from the source</returns>
		static protected void ReflectFields( object source, object destination )
		{
			Type sourceType = (source is Type) ? (Type)source : source.GetType();
			Type destinationType = (source is Type) ? (Type)destination : destination.GetType();

			FieldInfo[] fields = sourceType.GetFields( BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.GetField | BindingFlags.Instance );
			foreach( FieldInfo source_info in fields )
			{
				MemberInfo dest_info;
				dest_info = destination.GetType().GetField( source_info.Name );
				if( dest_info != null ) 
				{
					ReflectDude( source, source_info, destination, dest_info );
				}
				else
				{
					dest_info = destination.GetType().GetProperty( source_info.Name );
					if( dest_info != null ) 
					{
						ReflectDude( source, source_info, destination, dest_info );
					}
				}
			}
		}


		/// <summary>
		/// Map the data in the source object to a new instance of the destination object using reflection
		/// </summary>
		/// <param name="source">Instance of the data object to be coppied</param>
		/// <param name="destination">The type of object to be returned</param>
		/// <returns>An new instance of the destination object containing the data valued from the source</returns>
		static protected void ReflectProperties( object source, object destination )
		{
			Type sourceType = (source is Type) ? (Type)source : source.GetType();
			Type destinationType = (source is Type) ? (Type)destination : destination.GetType();

			PropertyInfo[] props = sourceType.GetProperties( BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.GetProperty | BindingFlags.Instance );
			foreach( PropertyInfo source_info in props )
			{
				MemberInfo dest_info;
				dest_info = destination.GetType().GetProperty( source_info.Name );
				if( dest_info != null ) 
				{
					ReflectDude( source, source_info, destination, dest_info );
				}
				dest_info = destination.GetType().GetField( source_info.Name );
				if( dest_info != null ) 
				{
					ReflectDude( source, source_info, destination, dest_info );
				}
			}
		}


		/// <summary>
		/// This dude maps Fields to Properties and visa-versa
		/// </summary>
		static protected void ReflectDude( object source, MemberInfo source_info, object destination, MemberInfo destination_info )
		{
			Type source_x_type    = null;
			object source_x_value = null;

			Type destination_x_type = null;
			object destination_x_value = null;


			// Determine the Source type and value
			if( source_info is FieldInfo ) 
			{
				FieldInfo info = (FieldInfo) source_info; 
				source_x_value = info.GetValue( source );
				source_x_type  = info.FieldType;
			}
			else if( source_info is PropertyInfo )
			{
				PropertyInfo info = (PropertyInfo) source_info; 
				source_x_value    = info.GetValue( source, null );
				source_x_type     = info.PropertyType;
			}

			// Determine the Source type and value
			if( destination_info is FieldInfo ) 
			{
				FieldInfo info      = (FieldInfo) destination_info; 
				destination_x_value = info.GetValue( destination );
				destination_x_type  = info.FieldType;
			}
			else if( destination_info is PropertyInfo )
			{
				PropertyInfo info   = (PropertyInfo) destination_info; 
				destination_x_value = info.GetValue( destination, null );
				destination_x_type  = info.PropertyType;
			}

			// Now figure out what to do to whom
			if( destination_info.DeclaringType.IsClass )
			{
				if( source_x_type == destination_x_type )
				{
					DoSetValue( destination, destination_info, source_x_value );
				}
				else if( destination_x_type.IsEnum && source_x_type.IsEnum )
				{
					object o = Enum.Parse( destination_x_type, source_x_value.ToString());
					DoSetValue( destination, destination_info, o );
				}
				else if( destination_x_type.IsArray && source_x_type.IsArray )
				{
					object o = MapArray_Reflection( source_x_value, destination_x_type );
					DoSetValue( destination, destination_info, o );
				}
				else 
				{
					// WARNING!!!  Going recursive!
					object o = MapIt_Reflection( source_x_value, destination_x_type );
					DoSetValue( destination, destination_info, o );
				}
			}
			else
			{
				DoSetValue( destination, destination_info, source_x_value );
			}
		}


		/// <summary>
		/// Set the destination object and property/field to the new value
		/// </summary>
		static protected void DoSetValue( object destination, MemberInfo destination_info, object new_value )
		{
			if( destination_info is FieldInfo )
			{
				((FieldInfo)destination_info).SetValue( destination, new_value ); 
			}
			else
			{
				((PropertyInfo)destination_info).SetValue( destination, new_value, null );
			}
		}

		/// <summary>
		/// Create an array of objects using reflection
		/// </summary>
		/// <param name="source">Source array of objects</param>
		/// <param name="type">Type of the new array of object</param>
		/// <returns></returns>
		protected static object[] MapArray_Reflection( object source, Type type )
		{
			// Like kinds of arrays 
			if( type == source.GetType().GetElementType() )
			{
				return (object[])source;
			}

			ArrayList tempList = new ArrayList( );

			foreach( object element in (object[])source )
			{
				tempList.Add( MapIt_Reflection( element, type.GetElementType() ) );
			}

			return (object[]) tempList.ToArray( type.GetElementType() );
		}
	}
}

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