Click here to Skip to main content
15,885,216 members
Articles / Programming Languages / Visual Basic

Automatic Implementation of the Event-Based Asynchronous Pattern

Rate me:
Please Sign up or sign in to vote.
4.78/5 (32 votes)
26 Nov 2008CPOL20 min read 63.2K   912   101  
Implement the event-based asynchronous pattern automatically with this code generator
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace AsyncGen
{
    /// <summary>
    /// Indicates to AsyncGen that it should process this method and allows you to customize the generated code.
    /// </summary>
	[AttributeUsage(AttributeTargets.Method)]
	public sealed class GenerateAsyncOperationAttribute : Attribute
	{
        /// <summary>
        /// Default constructor.
        /// </summary>
		public GenerateAsyncOperationAttribute()
		{
		}

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="baseName">Same as the <see cref="BaseName"/> property.</param>
		public GenerateAsyncOperationAttribute(string baseName)
		{
			this.baseName = baseName;
		}

        /// <summary>
        /// Gets or sets a string that is used to name the client class members that implement this asynchronous operation.
        /// </summary>
        /// <remarks><para>If this property is not specified, the base name is the name of the original method.</para>
        /// <para>If a method is overloaded, use a different base name for each overload.</para></remarks>
        public string BaseName
        {
            get { return baseName; }
            set { baseName = value; }
        }

        /// <summary>
        /// Gets or sets the name of the method used to start the asynchronous operation.
        /// </summary>
        /// <remarks>If this property is not specified, the name of the method is &lt;<see cref="BaseName"/>&gt;Async.</remarks>
        public string StartMethodName
        {
            get { return startMethodName; }
            set { startMethodName = value; }
        }

        /// <summary>
        /// Gets or sets the name of the event to raise when the operation has completed.
        /// </summary>
        /// <remarks>If this property is not specified, the name of the event is &lt;<see cref="BaseName"/>&gt;Completed.</remarks>
        public string CompletedEventName
        {
            get { return completedEventName; }
            set { completedEventName = value; }
        }

        /// <summary>
        /// Gets or sets the name of the structure that holds the output of the operation.
        /// </summary>
        /// <remarks>If this property is not specified, the name of the structure is &lt;<see cref="BaseName"/>&gt;Output.</remarks>
        public string OutputTypeName
        {
            get { return outputTypeName; }
            set { outputTypeName = value; }
        }

        /// <summary>
        /// Gets or sets the name of the method that the application should call to cancel the operation.
        /// </summary>
		/// <remarks>
        /// <para>If this property is not specified, the name of the method is &lt;<see cref="BaseName"/>&gt;AsyncCancel.</para>
        /// <para><list>
		/// <item>If CancelMethodName == <c>null</c>, don't generate a Cancel method.</item>
		/// <item>If CancelMethodName == <see cref="String.Empty"/>, use the base name to construct the Cancel method name.</item>
		/// </list></para>
        /// <para>When you set <see cref="CancelMethodName"/> to any non-null value, <see cref="GenerateCancelMethod"/> is set to <c>true</c>.</para>
        /// <para>When you set <see cref="GenerateCancelMethod"/> to <c>true</c>, the name of the cancel method is set to &lt;<see cref="BaseName"/>&gt;AsyncCancel.</para>
        /// <para>Use either <see cref="CancelMethodName"/> or <see cref="GenerateCancelMethod"/>, not both.</para></remarks>
		public string CancelMethodName
		{
			get
			{
				return cancelMethodName;
			}
			set
			{
                cancelMethodName = value;
			}
		}

        /// <summary>
        /// Gets or sets a value indicating whether to generate a cancel method.
        /// </summary>
        /// <remarks><para>By default, this property is set to <c>false</c>.  Set it to <c>true</c> only if your server supports cancellation.</para>
        /// <para>When you set <see cref="CancelMethodName"/> to any non-null value, <see cref="GenerateCancelMethod"/> is set to <c>true</c>.</para>
        /// <para>When you set <see cref="GenerateCancelMethod"/> to <c>true</c>, the name of the cancel method is set to &lt;<see cref="BaseName"/>&gt;AsyncCancel.</para>
        /// <para>Use either <see cref="CancelMethodName"/> or <see cref="GenerateCancelMethod"/>, not both.</para></remarks>
		public bool GenerateCancelMethod
		{
			get
			{
				return (cancelMethodName != null);
			}
			set
			{
				if (!value)
				{
					cancelMethodName = null;
				}
				else if (cancelMethodName == null)
				{
					cancelMethodName = string.Empty;
				}
                Debug.Assert((cancelMethodName != null) == value);
			}
		}

        /// <summary>
        /// Gets or sets the type of the callback interface for this operation.
        /// </summary>
        public Type CallbackInterface
        {
            get { return callbackInterface; }
            set { callbackInterface = value; }
        }

        private string baseName = string.Empty;
        private string startMethodName = string.Empty;
        private string completedEventName = string.Empty;
        private string outputTypeName = string.Empty;
        private string cancelMethodName = null; // By default, don't generate a Cancel method.
        private Type callbackInterface;
    }
}

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
Software Developer (Senior) Philips Healthcare
Israel Israel
I got my B.Sc. in Mathematics and Computer Science from Tel Aviv University in 1997. Since then I have developed software in UNIX, Win32 and .NET. I currently live in Haifa.

Comments and Discussions