How to Create a Simple Enterprise Library Cache Manager Provider for Velocity
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:

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

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:

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 newVelocityCacheManager
class)
After doing so, the wizard should look like:

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:

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 ofVelocityCacheManager
in the configuration file. Could beMultiple
if I wanted to have more then one node)
The following figure shows the Chosen parameters:

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:

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:

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.