Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

How to Create a Simple Enterprise Library Cache Manager Provider for Velocity

4.67/5 (4 votes)
31 Jul 2010CPOL3 min read 35.5K  
The article shows how to create a simple Velocity cache manager provider using the Application Block Software Factory.

Introduction

The article includes a recipe for creating a simple Velocity cache manager provider using the Application Block Software Factory.

Creating the Project

The first thing to do is to create the project.
If you don’t have Application Block Software Factory installed on your computer, then you can read an old post that I wrote in order to install it.

In VS2008, choose the Guidance Packages –> Application Block Software Factory project type and in it choose the Provider Library template like in the following figure:

Create a New Project

When the Create New Provider Library form appears, fill in the relevant details and press the Finish button:

Create New Provider Library

Creating the Velocity Cache Manager Provider

After we generated the project, the next thing to do is to create the Velocity Cache Manager provider. First add a reference to the Caching Application Block. After that, click the right mouse button on the VelocityCacheProvider class library project and in the Application Block Software Factory menu choose the New Provider (Typed) menu item:

Create New Provider

This will open the New Provider wizard.
Fill in the following details:

  • Name – VelocityCacheManager (The provider name)
  • Provider Interface – ICacheManager (The interface that the provider implements)
  • Provider Base Class – ICacheManager (The base class that the provider extends)
  • Configuration Base Class – CustomCacheManagerData (The configuration class that helps to create a new VelocityCacheManager class)

After doing so, the wizard should look like:

New Provider (Typed)

Press the Finish button to create the provider.

Velocity Cache Manager Implementation

Add references to CacheBaseLibrary and to ClientLibary DLLs which are found in the Velocity deployment directory.

The following is the implementation of VelocityCacheManager:

C#
using Microsoft.Data.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace Microsoft.Practices.EnterpriseLibrary.Caching.Velocity
{
    [ConfigurationElementType(typeof(VelocityCacheManagerData))]
    public class VelocityCacheManager : ICacheManager
    {
        #region Consts

        private const string DefaultRegionName = "default";

        #endregion

        #region Members

        private DataCache _realCache;

        #endregion

        #region Ctor

        /// <summary>
        /// <para>Initializes a new instance of the <see
        /// cref="VelocityCacheManager"/>.</para>
        /// </summary>
        /// <param name="configuration">The configuration object
        /// used to set the runtime values</param>
        public VelocityCacheManager(VelocityCacheManagerData configuration)
        {
            var servers = CreateCacheEndpoints(configuration);
            var factory = new DataCacheFactory
		(servers, configuration.RoutingClient, configuration.LocalCache);
            _realCache = factory.GetCache(configuration.NamedCache);
        }

        #endregion

        #region Methods

        private static DataCacheServerEndpoint[] CreateCacheEndpoints(
           VelocityCacheManagerData configuration)
        {
            var servers = new DataCacheServerEndpoint[1];
            servers[0] = new DataCacheServerEndpoint(configuration.HostName,
		configuration.CachePort, configuration.CacheHostName);
            return servers;
        }

        #endregion

        #region ICacheManager Members

        public void Add(string key, object value, CacheItemPriority scavengingPriority,
	ICacheItemRefreshAction refreshAction, params ICacheItemExpiration[] expirations)
        {
            // other parameters are currently ignored
            _realCache.Add(key, value);
        }

        public void Add(string key, object value)
        {
            _realCache.Add(key, value);
        }

        public bool Contains(string key)
        {
            object obj = _realCache.Get(key);
            return obj != null;
        }

        public int Count
        {
            get
            {
                int counter = 0;
                foreach (var item in _realCache.GetObjectsInRegion("default"))
                {
                    counter++;
                }
                return counter;
            }
        }

        public void Flush()
        {
            _realCache.ClearRegion(DefaultRegionName);
        }

        public object GetData(string key)
        {
            return _realCache.Get(key);
        }

        public void Remove(string key)
        {
            _realCache.Remove(key);
        }

        public object this[string key]
        {
            get
            {
                return _realCache.Get(key);
            }
        }

        #endregion
    }
}

The following is the implementation of the VelocityCacheManagerData:

C#
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.ObjectBuilder2;

namespace Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration
{
    /// <summary>
    /// Represents the configuration data for a <see
    /// cref="VelocityCacheManager"/>.
    /// </summary>
    [Assembler(typeof(VelocityCacheManagerAssembler))]
    public class VelocityCacheManagerData : CustomCacheManagerData
    {
        #region Consts

        private const string RoutingClientString = "RoutingClient";
        private const string LocalCacheString = "LocalCache";
        private const string HostNameString = "HostName";
        private const string CachePortString = "CachePort";
        private const string CacheHostNameString = "CacheHostName";
        private const string NamedCacheString = "NamedCache";

        #endregion

        #region Ctor

        /// <summary>
        /// Initializes a new instance of the <see
        /// cref="VelocityCacheManagerData"/> class.
        /// </summary>
        public VelocityCacheManagerData()
            : base("VelocityCacheManager", typeof(VelocityCacheManager))
        {
           RoutingClient = false;
           LocalCache = false;
           HostName = "localhost";
           CachePort = 22233;
           CacheHostName = "DistributedCacheService";
           NamedCache = "default";
        }

        public VelocityCacheManagerData(string name, bool routingClient,
	bool localCache, string hostName, int cachePort,
	string cacheHostName, string namedCache)
            : base(name, typeof(VelocityCacheManager))
        {
            RoutingClient = routingClient;
            LocalCache = localCache;
            HostName = hostName;
            CachePort = cachePort;
            CacheHostName = cacheHostName;
            NamedCache = namedCache;
        }

        #endregion

        #region Properties

        [ConfigurationProperty(RoutingClientString, IsRequired = true)]
        public bool RoutingClient
        {
            get
            {
                return (bool)base[RoutingClientString];
            }
            set
            {
                base[RoutingClientString] = value;
            }
        }

        [ConfigurationProperty(LocalCacheString, IsRequired = true)]
        public bool LocalCache
        {
            get
            {
                return (bool)base[LocalCacheString];
            }
            set
            {
                base[LocalCacheString] = value;
            }
        }

        [ConfigurationProperty(HostNameString, IsRequired = true)]
        public string HostName
        {
            get
            {
                return (string)base[HostNameString];
            }
            set
            {
                base[HostNameString] = value;
            }
        }

        [ConfigurationProperty(CachePortString, IsRequired = true)]
        public int CachePort
        {
            get
            {
                return (int)base[CachePortString];
            }
            set
            {
                base[CachePortString] = value;
            }
        }

        [ConfigurationProperty(CacheHostNameString, IsRequired = true)]
        public string CacheHostName
        {
            get
            {
                return (string)base[CacheHostNameString];
            }
            set
            {
                base[CacheHostNameString] = value;
            }
        }

        [ConfigurationProperty(NamedCacheString, IsRequired = true)]
        public string NamedCache
        {
            get
            {
                return (string)base[NamedCacheString];
            }
            set
            {
                base[NamedCacheString] = value;
            }
        }

        #endregion
    }

    /// <summary>
    /// This type supports the Enterprise Library infrastructure and is not
    /// intended to be used directly from your code.
    /// Represents the process to build a <see
    /// cref="VelocityCacheManager"/> described by a <see
    /// cref="VelocityCacheManagerData"/> configuration object.
    /// </summary>
    /// <remarks>This type is linked to the <see
    /// cref="VelocityCacheManagerData"/> type and it is
    /// used by the Custom Factory
    /// to build the specific
    /// <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager"/>
    /// object represented by the configuration object.
    /// </remarks>
    public class VelocityCacheManagerAssembler : IAssembler<ICacheManager,
	CacheManagerDataBase>
    {
      /// <summary>
      /// Builds a <see cref="VelocityCacheManager"/> based
      /// on an instance of
      /// <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.
      /// CustomCacheManagerData"/>.
      /// </summary>
      /// <param name="context">The <see cref="IBuilderContext"/>
      /// that represents the current building process.</param>
      /// <param name="objectConfiguration">The configuration object that
      /// describes the object to build. Must be an instance of
      /// <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.
      /// CustomCacheManagerData"/>.</param>
      /// <param name="configurationSource">The source for configuration objects.</param>
      /// <param name="reflectionCache">The cache to use retrieving
      /// reflection information.</param>
      /// <returns>A fully initialized instance of
      /// <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager"/>.
      /// </returns>
      public ICacheManager Assemble(IBuilderContext context,
	CacheManagerDataBase objectConfiguration,
	IConfigurationSource configurationSource,
	ConfigurationReflectionCache reflectionCache)
      {
        VelocityCacheManagerData castObjectConfiguration =
			(VelocityCacheManagerData)objectConfiguration;
        VelocityCacheManager createdObject =
			new VelocityCacheManager(castObjectConfiguration);
        return createdObject;
      }
   }
}

Creating the VelocityCacheManager Design Configuration

Having the implementation of the VelocityCacheManager is enough to use it, but you'll probably want to use it also through the configuration tool of Enterprise Library. The following steps will help you to create the design configuration for the Enterprise Library configuration tool.

Step 1

In the created VelocityCacheProvider.Configuration.Design class library, add references to the following DLLs:

  • Microsoft.Practices.EnterpriseLibrary.Caching
  • Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.Design
  • VelocityCacheProvider

Step 2

Press right mouse button on the VelocityCacheProvider.Configuration.Design and in the Application Block Software Factory menu, choose the Crate Design-Time Provider Node menu item:

Create Design-Time Provider Node

In the wizard, choose the following:

  • Node Name – VelocityCacheManagerNode (The node name in the configuration)
  • Runtime Configuration Type – CacheManagerDataBase (The class that the node will be in runtime)
  • Base Design Node – CustomCacheManagerNode (The base class for the design node)
  • Parent UI Node – CacheManagerCollectionNode (The node who holds our created node)
  • Cardinality – Single (enable only single node of VelocityCacheManager in the configuration file. Could be Multiple if I wanted to have more then one node)

The following figure shows the Chosen parameters:

Create Design-Time Provider Node Wizard

Pressing Finish will create all the relevant data and classes.

Step 3

Implement the created classes.

VelocityCacheManagerNode implementation:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing.Design;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.Validation;
using Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.
	Configuration.Design.Properties;
using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration;

namespace Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.Design
{
    /// <summary>
    /// Represents a <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.
    /// Velocity.Configuration.VelocityCacheManagerData"/> configuration element.
    /// </summary>
    public class VelocityCacheManagerNode : Microsoft.Practices.EnterpriseLibrary.
		Caching.Configuration.Design.CustomCacheManagerNode
    {
        /// <summary>
        /// Initialize a new instance of the <see cref="VelocityCacheManagerNode"/> class.
        /// </summary>
        public VelocityCacheManagerNode()
            : this(new VelocityCacheManagerData(Resources.VelocityCacheManagerNodeName,
		false, false, "localhost", 22233, "DistributedCacheService", "default"))
        {
        }

        /// <summary>
        /// Initialize a new instance of the <see cref="VelocityCacheManagerNode"/>
        /// class with a <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.
        /// Velocity.Configuration.VelocityCacheManagerData"/> instance.
        /// </summary>
        /// <param name="data">A <see cref="Microsoft.Practices.
        /// EnterpriseLibrary.Caching.Velocity.Configuration.VelocityCacheManagerData"/>
        /// instance</param>
        public VelocityCacheManagerNode(VelocityCacheManagerData data)
        {
            if (null == data)
            {
                throw new ArgumentNullException("error in creating the data node -
					VelocityCacheManagerData is null");
            }

            Rename(data.Name);
            this.routingClient = data.RoutingClient;
            this.localCache = data.LocalCache;
            this.hostName = data.HostName;
            this.cachePort = data.CachePort;
            this.cacheHostName = data.CacheHostName;
            this.namedCache = data.NamedCache;
            Type = typeof(VelocityCacheManager).ToString();
        }

        /// <summary>
        /// Gets the <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.
        /// Velocity.Configuration.VelocityCacheManagerData"/> this node represents.
        /// </summary>
        /// <value>
        /// The <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.
        /// Velocity.Configuration.VelocityCacheManagerData"/> this node represents.
        /// </value>
        [Browsable(false)]
        public override CacheManagerDataBase CacheManagerData
        {
            get
            {
                VelocityCacheManagerData data = new VelocityCacheManagerData();
                data.Name = this.Name;
                data.RoutingClient = this.routingClient;
                data.LocalCache = this.localCache;
                data.HostName = this.hostName;
                data.CachePort = this.cachePort;
                data.CacheHostName = this.cacheHostName;
                data.NamedCache = this.namedCache;
                return data;
            }
        }

        /// <summary>
        /// Releases the unmanaged resources used by the
        /// <see cref="VelocityCacheManagerNode"/> and optionally releases
        /// the managed resources.
        /// </summary>
        /// <param name="disposing">
        /// <see langword="true"/> to release both managed and unmanaged resources;
        /// <see langword="false"/> to release only unmanaged resources.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
            }
            base.Dispose(disposing);
        }

        private System.Boolean routingClient;

        /// <summary>
        ///
        /// </summary>
        /// <value>
        ///
        /// </value>
        [SRDescription("RoutingClientDescription", typeof(Resources))]
        [SRCategory("CategoryGeneral", typeof(Resources))]
        public System.Boolean RoutingClient
        {
            get { return this.routingClient; }
            set { this.routingClient = value; }
        }

        private System.Boolean localCache;

        /// <summary>
        ///
        /// </summary>
        /// <value>
        ///
        /// </value>
        [SRDescription("LocalCacheDescription", typeof(Resources))]
        [SRCategory("CategoryGeneral", typeof(Resources))]
        public System.Boolean LocalCache
        {
            get { return this.localCache; }
            set { this.localCache = value; }
        }

        private System.String hostName;

        /// <summary>
        ///
        /// </summary>
        /// <value>
        ///
        /// </value>
        [SRDescription("HostNameDescription", typeof(Resources))]
        [SRCategory("CategoryGeneral", typeof(Resources))]
        public System.String HostName
        {
            get { return this.hostName; }
            set { this.hostName = value; }
        }

        private System.Int32 cachePort;

        /// <summary>
        ///
        /// </summary>
        /// <value>
        ///
        /// </value>
        [SRDescription("CachePortDescription", typeof(Resources))]
        [SRCategory("CategoryGeneral", typeof(Resources))]
        public System.Int32 CachePort
        {
            get { return this.cachePort; }
            set { this.cachePort = value; }
        }

        private System.String cacheHostName;

        /// <summary>
        ///
        /// </summary>
        /// <value>
        ///
        /// </value>
        [SRDescription("CacheHostNameDescription", typeof(Resources))]
        [SRCategory("CategoryGeneral", typeof(Resources))]
        public System.String CacheHostName
        {
            get { return this.cacheHostName; }
            set { this.cacheHostName = value; }
        }

        private System.String namedCache;

        /// <summary>
        ///
        /// </summary>
        /// <value>
        ///
        /// </value>
        [SRDescription("NamedCacheDescription", typeof(Resources))]
        [SRCategory("CategoryGeneral", typeof(Resources))]
        public System.String NamedCache
        {
            get { return this.namedCache; }
            set { this.namedCache = value; }
        }
    }
}

NodeMapRegistrar implementation:

C#
//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Application Block Software Factory
//===============================================================================
// Copyright © Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;
using Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.
	Design.Properties;

namespace Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.Design
{
    sealed class NodeMapRegistrar : Microsoft.Practices.EnterpriseLibrary.
	Configuration.Design.NodeMapRegistrar
    {
        public NodeMapRegistrar(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
        }

        public override void Register()
        {
            AddSingleNodeMap(Resources.VelocityCacheManagerNodeUICommandText,
               typeof(VelocityCacheManagerNode),
               typeof(VelocityCacheManagerData));
        }
    }
}

CommandRegistrar implementation:

C#
//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Application Block Software Factory
//===============================================================================
// Copyright © Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;
using Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.
	Design.Properties;

namespace Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.Design
{
    sealed partial class CommandRegistrar : Microsoft.Practices.
		EnterpriseLibrary.Configuration.Design.CommandRegistrar
    {
        public CommandRegistrar(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
        }

        public override void Register()
        {
            AddVelocityCacheManagerNodeCommand();
            AddDefaultCommands(typeof(VelocityCacheManagerNode));
        }
    }
}

CommandRegistrar.VelocityCacheManagerNode implementation:

using System;
using Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.
	Configuration.Design.Properties;
using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.Design;

namespace Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.Design
{
    sealed partial class CommandRegistrar
    {
        private void AddVelocityCacheManagerNodeCommand()
        {
            AddSingleChildNodeCommand(
                Resources.VelocityCacheManagerNodeUICommandText,
                Resources.VelocityCacheManagerNodeUICommandLongText,
                typeof(VelocityCacheManagerNode),
                typeof(CacheManagerCollectionNode));
        }
    }
}

Step 4

Edit the Resources file to look like:

Resources File

That is it.

Now you only need to drop the two generated DLLs to the configuration tool’s directory and you are clear to go and use the tool to configure the VelocityCacheManager. The following figure shows how it looks like inside the configuration tool of Enterprise Library:

VelocityCacheManager in EL configuration tool

Summary

The article described how to create a simple Velocity cache manager for Enterprise Library’s Caching Application Block. I also described how to integrated the created provider library to the configuration tool of Enterprise Library. You can download the provider library from here.

You can use the provider I wrote and change the code I provided in your implementation.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)