Click here to Skip to main content
15,886,541 members
Articles / Programming Languages / C# 4.0

Low impact images

Rate me:
Please Sign up or sign in to vote.
4.89/5 (44 votes)
8 Jun 2010CPOL5 min read 78K   890   57  
This article describes one way of dealing with the thorny issue of image lifetime in applications.
using System;
using System.Collections.Generic;
using System.Drawing;

namespace Pete.OHanlon
{
    /// <summary>
    /// This class removes the need to manage the retrieval and storage of images in your
    /// application. With this implementation, it's possible to store images as weakly
    /// referenced objects which helps to lessen the impact your application will have as
    /// images are removed and recreated as needed.
    /// </summary>
    public sealed class ImageManager : IDisposable
    {
        #region Members
        private static readonly object SyncLock = new object();
        private static ImageManager _instance;
        private Dictionary<string, ImageCache> _images = new Dictionary<string, ImageCache>();
        #endregion

        /// <summary>
        /// A no-op constructor.
        /// </summary>
        private ImageManager() { }

        /// <summary>
        /// Get the <see cref="ImageManager"/> instance.
        /// </summary>
        public static ImageManager Instance
        {
            get
            {
                lock (SyncLock)
                {
                    if (_instance == null)
                        _instance = new ImageManager();
                }
                return _instance;
            }
        }

        /// <summary>
        /// Returns the number of <see cref="ImageManager"/> items.
        /// </summary>
        public int ImageCount
        {
            get
            {
                return _images.Count;
            }
        }

        /// <summary>
        /// Identify whether or not a key has already been added to the
        /// collection of images.
        /// </summary>
        /// <param name="key">The key to check.</param>
        /// <returns>True if the key has already been added, false otherwise.</returns>
        public bool IsKeyPresent(string key)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");
            lock (SyncLock)
            {
                return _images.ContainsKey(key);
            }
        }

        /// <summary>
        /// Remove the item identified by key.
        /// </summary>
        /// <param name="key">The key of the item to remove.</param>
        public void Remove(string key)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");
            lock (SyncLock)
            {
                if (_images.ContainsKey(key))
                {
                    _images[key].Dispose();
                    _images.Remove(key);
                }
            }
        }

        /// <summary>
        /// Add an image to the images cache.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="path"></param>
        public void Add(string key, string path)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");
            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");
            lock (SyncLock)
            {
                if (_images.ContainsKey(key))
                {
                    throw new ArgumentException(string.Format("The key {0} is already present.", key));
                }

                ImageCache wrapper = new ImageCache(path);
                _images.Add(key, wrapper);
                wrapper = null;
            }
        }

        /// <summary>
        /// Get the image associated with the relevant key.
        /// </summary>
        /// <param name="key">The key to get the image with.</param>
        /// <returns>The relevant image.</returns>
        public Image Image(string key)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");
            lock (SyncLock)
            {
                if (!_images.ContainsKey(key))
                {
                    throw new ArgumentException("There is no image matching this key");
                }
                Image img = _images[key].Image;
                return img;
            }
        }

        #region IDisposable Members
        /// <summary>
        /// Dispose of any unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            OnDispose();
        }

        private void OnDispose()
        {
            foreach (KeyValuePair<string, ImageCache> kvp in _images)
            {
                kvp.Value.Dispose();
            }
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}

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
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.

I am not the Stig, but I do wish I had Lotus Tuned Suspension.

Comments and Discussions