Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

SingleInstance(Of T) Class for Windows Phone 7

0.00/5 (No votes)
14 May 2011 1  
This post aims to provide a way to implement lazy initialization in a multi threaded environment using the SingleInstance(Of T) Class.

When building applications for a mobile operating system such as Windows Phone 7 (WP7), you might want (at times) to defer the creation of large objects, specifically when this creation is going to increase memory consumption. While in the desktop CLR there is the Lazy(Of T) Class, when working on WP7, this class does not exist (at least not at the time of this writing).

I find it a very repetitive task to manually produce a single instance object:

  1. Make its constructor private.
  2. Write the code for initialization.
  3. Provide a getter method that returns the one and only instance.

While you cannot avoid step 2, it is possible to create a generic class that produces step 1 and step 3. Then, from the class constructor, you can pass the code that creates the object using a Func(TResult) Delegate.

Update: The first version of the SingleInstance(Of T) class provided an option to create an instance (Of T) using the thread pool. This option is removed in the current version.

SingleInstance(Of T) Class

using System;
using System.Threading;

public sealed class SingleInstance<T> where T : class
{
    private readonly Object m_lockObj = new Object();
    private readonly Func<T> m_delegate;
    private Boolean m_isDelegateInvoked;

    private T m_value;

    /// <summary>
    /// Initializes a new instance of the
    /// <see cref="SingleInstance&lt;T&gt;"/> class.
    /// </summary>
    public SingleInstance()
        : this(() => default(T)) { }

    /// <summary>
    /// Initializes a new instance of the
    /// <see cref="SingleInstance&lt;T&gt;"/> class.
    /// </summary>
    /// <param name="delegate">The @delegate.</param>
    public SingleInstance(Func<T> @delegate)
    {
        m_delegate = @delegate;
    }

    /// <summary>
    /// Gets the instance.
    /// </summary>
    /// <value>The instance.</value>
    public T Instance
    {
        get
        {
            if (!m_isDelegateInvoked)
            {
                T temp = m_delegate();
                Interlocked.CompareExchange<T>(ref m_value, temp, null);

                Boolean lockTaken = false;

                try
                {
                    // WP7 does not support the overload with the
                    // Boolean indicating if the lock was taken.
                    Monitor.Enter(m_lockObj); lockTaken = true;

                    m_isDelegateInvoked = true;
                }
                finally
                {
                    if (lockTaken) { Monitor.Exit(m_lockObj); }
                }
            }

            return m_value;
        }
    }
}

The SingleInstance(Of T) class has many differences from the System.Lazy(Of T) class in the desktop CLR.

  • The System.Lazy(Of T) class takes a LazyThreadSafetyMode enumeration. This enumeration contains 3 members (None, PublicationOnly, ExecutionAndPublication). The SingleInstance(Of T) class uses the interlocked constructs to produce a single instance. This is similar with passing LazyThreadSafetyMode.ExecutionAndPublication in the System.Lazy(Of T) class.
  • The System.Lazy(Of T) class works with classes (reference types) and structs (value types). The value types are boxed internally. The SingleInstance(Of T) class works only with reference types.
  • Finally, the System.Lazy(Of T) class is written, tested and supported by Microsoft, while the SingleInstance(Of T) is not.

Keep in mind that the SingleInstance(Of T) class uses a Func(TResult) delegate. There is a known performance hit when calling delegates compared to direct method calls. (See the Delegates section here.)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here