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

July 27, 2009

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


In the previous post How to Create a Simple Enterprise Library Cache Manager Provider for Velocity
I promised to give the
recipe of how to create
the a simple Velocity cache
manager provider using the
Application Block Software
Factory
. In this post I’ll keep
my promise.


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 appear, 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:



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:



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:



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:



//===============================================================================
// 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:



//===============================================================================
// 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 post 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 to
your implementation.


Enjoy!

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*