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 new VelocityCacheManager
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
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)
{
_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
{
[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
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
}
public class VelocityCacheManagerAssembler : IAssembler<ICacheManager,
CacheManagerDataBase>
{
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 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:
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
{
public class VelocityCacheManagerNode : Microsoft.Practices.EnterpriseLibrary.
Caching.Configuration.Design.CustomCacheManagerNode
{
public VelocityCacheManagerNode()
: this(new VelocityCacheManagerData(Resources.VelocityCacheManagerNodeName,
false, false, "localhost", 22233, "DistributedCacheService", "default"))
{
}
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();
}
[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;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
private System.Boolean routingClient;
[SRDescription("RoutingClientDescription", typeof(Resources))]
[SRCategory("CategoryGeneral", typeof(Resources))]
public System.Boolean RoutingClient
{
get { return this.routingClient; }
set { this.routingClient = value; }
}
private System.Boolean localCache;
[SRDescription("LocalCacheDescription", typeof(Resources))]
[SRCategory("CategoryGeneral", typeof(Resources))]
public System.Boolean LocalCache
{
get { return this.localCache; }
set { this.localCache = value; }
}
private System.String hostName;
[SRDescription("HostNameDescription", typeof(Resources))]
[SRCategory("CategoryGeneral", typeof(Resources))]
public System.String HostName
{
get { return this.hostName; }
set { this.hostName = value; }
}
private System.Int32 cachePort;
[SRDescription("CachePortDescription", typeof(Resources))]
[SRCategory("CategoryGeneral", typeof(Resources))]
public System.Int32 CachePort
{
get { return this.cachePort; }
set { this.cachePort = value; }
}
private System.String cacheHostName;
[SRDescription("CacheHostNameDescription", typeof(Resources))]
[SRCategory("CategoryGeneral", typeof(Resources))]
public System.String CacheHostName
{
get { return this.cacheHostName; }
set { this.cacheHostName = value; }
}
private System.String namedCache;
[SRDescription("NamedCacheDescription", typeof(Resources))]
[SRCategory("CategoryGeneral", typeof(Resources))]
public System.String NamedCache
{
get { return this.namedCache; }
set { this.namedCache = value; }
}
}
}
NodeMapRegistrar
implementation:
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:
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.