Click here to Skip to main content
15,885,366 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.3K   6.9K   69  
Describes how to build a Windows Service using the Pegasus Library.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Runtime.Serialization;
using System.Reflection;

using Pegasus.Diagnostics;
using Pegasus.Reflection;

namespace Pegasus.Runtime.Serialization
{
	/// <summary>
	/// This class implements a basic object binder that will look for the given object type
	/// in the following order.
	/// 1. Uses the full assembly name
	/// 2. Uses a version independate assembly name
	/// 3. Uses a non-culture assembly name
	/// 4. Uses a non-strong name assembly (basicly just the assembly name at this point)
    /// 5. Uses just the full class name and matches with an assembly by the same name in the loaded assemblies
	/// </summary>
	public class ObjectSerializationBinder : SerializationBinder
	{
		// Local Instance Values
		private Dictionary<string, Type> m_typeTable = new Dictionary<string, Type>();
		private bool m_unknownTypeReplacement = false;

		/// <summary>
		/// Initializes a new instance of the <see cref="T:ObjectSerializationBinder"/> class.
		/// </summary>
		public ObjectSerializationBinder()
		{
			// Add changes to the pegasus type serialize objects

			// 8/16/06 - Reworked workflow the workflow (again)
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowEventInfo", typeof( Pegasus.Workflow.Service.WorkflowMessageService.WorkflowEventMessage ) );
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowEventInfo[]", typeof( Pegasus.Workflow.Service.WorkflowMessageService.WorkflowEventMessage[] ) );
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowEventType", typeof( object ) );
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowEventType[]", typeof( object[] ) );

			// 7/21/06 - Change/Rename the event info types for workflow
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowContext+WorkflowCompletedEventInfo", typeof( Pegasus.Workflow.Service.WorkflowMessageService.WorkflowEventMessage ) );
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowContext+WorkflowCompletedEventInfo[]", typeof( Pegasus.Workflow.Service.WorkflowMessageService.WorkflowEventMessage[] ) );
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowContext+WorkflowCompletedBindingType", typeof( object ) );
			AddTypeOverride( "Pegasus.Workflow.Service.WorkflowContext+WorkflowCompletedBindingType[]", typeof( object[] ) );
		}

		/// <summary>
		/// Gets or sets a value indicating whether to use unknown type replacement.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if unknown type replacement is used; otherwise, <c>false</c>.
		/// </value>
		public bool UnknownTypeReplacement
		{
			get
			{
				return m_unknownTypeReplacement;
			}
			
			set
			{
				m_unknownTypeReplacement = value;
			}
		}

		/// <summary>
		/// When overridden in a derived class, controls the binding of a serialized object to a type.
		/// </summary>
		/// <param name="assemblyName">Specifies the <see cref="T:System.Reflection.Assembly"></see> name of the serialized object.</param>
		/// <param name="typeName">Specifies the <see cref="T:System.Type"></see> name of the serialized object.</param>
		/// <returns>
		/// The type of the object the formatter creates a new instance of.
		/// </returns>
		public override Type BindToType( string assemblyName, string typeName )
		{
			// Check parameters
			ParamCode.AssertNotEmpty( assemblyName, "assemblyName" );
			ParamCode.AssertNotEmpty( typeName, "typeName" );

			// Try to bind to the given type
			TypeName typeNameParam = new TypeName( assemblyName, typeName );
			return BindToGivenType( typeNameParam, m_unknownTypeReplacement );
		}

        /// <summary>
        /// Binds to type.
        /// </summary>
        /// <param name="typeName">Name of the type.</param>
        public Type BindToType( TypeName typeName )
        {
            // Check parameters
            ParamCode.AssertNotNull( typeName, "typeName" );

            // Try to bind to the given type
            return BindToGivenType( typeName, m_unknownTypeReplacement );
        }

		/// <summary>
		/// Adds the type override.
		/// </summary>
		/// <param name="oldTypeName">Old name of the type.</param>
		/// <param name="newType">The new type.</param>
		protected void AddTypeOverride( string oldTypeName, Type newType )
		{
			m_typeTable.Add( oldTypeName, newType );
		}

		/// <summary>
		/// Binds to type specific.
		/// </summary>
		/// <param name="typeName">Name of the type.</param>
		/// <param name="unknownTypeReplacement">if set to <c>true</c> to replace unknown types with Object.</param>
		/// <returns></returns>
		private Type BindToGivenType( TypeName typeName, bool unknownTypeReplacement )
		{
			Type type = null;

			// Check if we have an override type registered.
			if( m_typeTable.ContainsKey( typeName.FullTypeName ) )
			{
				return m_typeTable[ typeName.FullTypeName ];
			}

			// If this is a generic type then we need to bind the sub types first
			// and replace anything that is out of date.
			if( typeName.IsGenericType || typeName.IsArrayItemGenericType )
			{
				ReadOnlyCollection<TypeName> parametersCollection = typeName.GenericParameters;
				int count = parametersCollection.Count;
				TypeName[] newTypeNames = new TypeName[ count ];

				for( int x = 0; x < count; x++ )
				{
					// Get the sub-type, sub-types can not be replaced.
					Type subType = BindToGivenType( parametersCollection[ x ], false );
					if( subType != null )
					{
						newTypeNames[ x ] = new TypeName( subType.AssemblyQualifiedName );
					}
					else
					{
						throw new TypeLoadException( string.Format( "Unable to find generic sub-type {0}, {1}, from {2}", parametersCollection[ x ].FullTypeName, parametersCollection[ x ].FullyQualifiedAssemblyName, typeName.FullyQualifiedTypeName ) );
					}
				}

				typeName = typeName.ReplaceGenericParameters( newTypeNames );
			}

			// Now we have all the sub-types or we just have the given type we can 
			// try to match it.
			try
			{
				// Try for an exact match
				type = Type.GetType( typeName.FullyQualifiedTypeName );
				if( type == null )
				{
					// Now check without the version
					type = BindToTypeWithoutVersion( typeName, unknownTypeReplacement );
				}
			}
			catch( FileLoadException )
			{
				// Now check without the version
				type = BindToTypeWithoutVersion( typeName, unknownTypeReplacement );
			}

			return type;
		}

		/// <summary>
		/// Binds to type without version.
		/// </summary>
		/// <param name="typeName">Name of the type.</param>
		/// <param name="unknownTypeReplacement">if set to <c>true</c> to replace unknown types with Object.</param>
		/// <returns></returns>
		private Type BindToTypeWithoutVersion( TypeName typeName, bool unknownTypeReplacement )
		{
			Type type = null;

			try
			{
				// Try again without the version 
				type = Type.GetType( typeName.GetFullyQualifiedTypeName( TypeNameFilter.ExcludeVersion ) );
				if( type == null )
				{
					// Now check without the culture
					type = BindToTypeWithoutCulture( typeName, unknownTypeReplacement );
				}
			}
			catch( FileLoadException )
			{
				// Now check without the culture
				type = BindToTypeWithoutCulture( typeName, unknownTypeReplacement );
			}

			return type;
		}

		/// <summary>
		/// Binds to type without culture.
		/// </summary>
		/// <param name="typeName">Name of the type.</param>
		/// <param name="unknownTypeReplacement">if set to <c>true</c> to replace unknown types with Object.</param>
		/// <returns></returns>
		private Type BindToTypeWithoutCulture( TypeName typeName, bool unknownTypeReplacement )
		{
			Type type = null;

			try
			{
				// Try again with out the version or the culture
				type = Type.GetType( typeName.GetFullyQualifiedTypeName( TypeNameFilter.ExcludeVersion | TypeNameFilter.ExcludeCulture ) );
				if( type == null )
				{
					// Now check without the public key
					type = BindToTypeWithoutPublicKey( typeName, unknownTypeReplacement );
				}
			}
			catch( FileLoadException )
			{
				// Now check without the public key
				type = BindToTypeWithoutPublicKey( typeName, unknownTypeReplacement );
			}

			return type;
		}

		/// <summary>
		/// Binds to type without public key.
		/// </summary>
		/// <param name="typeName">Name of the type.</param>
		/// <param name="unknownTypeReplacement">if set to <c>true</c> to replace unknown types with Object.</param>
		/// <returns></returns>
		private Type BindToTypeWithoutPublicKey( TypeName typeName, bool unknownTypeReplacement )
		{
			Type type = null;

			try
			{
				// Try again with out the version, the culture, or the public key
				type = Type.GetType( typeName.GetFullyQualifiedTypeName( TypeNameFilter.ExcludeVersion | TypeNameFilter.ExcludeCulture | TypeNameFilter.ExcludePublicKey ) );
				if( type == null )
				{
                    // Next bind with just the type name and assembly name matching
                    type = BindToTypeWithoutAssembly( typeName, unknownTypeReplacement );
				}
			}
			catch( FileLoadException )
			{
                // Next bind with just the type name and assembly name matching
                type = BindToTypeWithoutAssembly( typeName, unknownTypeReplacement );
			}

			return type;
		}

        private Type BindToTypeWithoutAssembly( TypeName typeName, bool unknownTypeReplacement )
        {
            // Try again by matching the assembly name with a loaded assembly and type name likewise
            foreach( Assembly assembly in AppDomain.CurrentDomain.GetAssemblies() )
            {
                if( assembly.FullName.StartsWith( typeName.AssemblyName ) )
                {
                    foreach( Type assemblyType in assembly.GetTypes() )
                    {
                        if( assemblyType.FullName == typeName.FullTypeName )
                        {
                            return assemblyType;
                        }
                    }
                }
            }

            if( unknownTypeReplacement )
            {
                return typeof( object );
            }
            else
            {
                return 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