DCSIMG
July 2009 - Posts - Gil Fink's Blog

Gil Fink's Blog

Fink about IT

News

Microsoft MVP

My Facebook Profile My Twitter Profile My Linkedin Profile

Locations of visitors to this page

Creative Commons License

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2012 Gil Fink

Hebrew Articles

Index Pages

My OSS Projects

English Articles

July 2009 - Posts

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

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!

Creating a Simple Enterprise Library Cache Provider for Velocity

Creating a Simple Enterprise Library Cache Provider for Velocity

I decided to write a simple Creating a Simple Enterprise Library Cache Provider for Velocity
cache manager provider for
Velocity (Microsoft Distributed
Cache
) using the Enterprise
Library
Application Block Software
Factory
.
You can download the solution from
here. If you put the two dll’s I provided
(Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.dll and
Microsoft.Practices.EnterpriseLibrary.Caching.Velocity.Configuration.Design.dll)
in the directory of EntLibConfig tool you’ll be able to use them in the tool like
in the following figure:
VelocityCacheManager in EL configuration tool

In a follow up post I’ll explain how I implemented the provider library in more details.

Enjoy!

DotNetKicks Image

Quick Tip – How to Enable Local Cache in Velocity (Microsoft Distributed Cache) Client

Quick Tip – How to Enable Local Cache in Velocity (Microsoft Distributed Cache) Client

Since I got this question twice .Net Framework New Logo
this week, I’m writing this post.
One of Velocity (Microsoft
Distributed Cache)
features is
called local cache. In this post I’ll
show how to enable that feature.

Velocity Client Local Cache

Local cache is a Velocity feature that can help speed up access on Velocity clients.
When enabled, a de-serialized copy of the object is saved in the client memory.
Before retrieving cached objects, the client cache will first checks whether the
object exists locally and if so will get it from the local cache.

Enabling Local Cache

There are two ways to enable local cache on a Velocity client:

  • The runtime way – the DataCacheFactory object has a constructor that gets
    as parameter whether the local cache is enabled.
    for example:
    DataCacheServerEndpoint[] servers = new DataCacheServerEndpoint[1];
    servers[0] = new DataCacheServerEndpoint("localhost",
                            22233, "DistributedCacheService");
     
    bool routingClient = false;
     
    // True = Enable local cache
    // False = Disable local cache
    bool localCache = false;
     
    var factory = new DataCacheFactory(servers,
        routingClient, localCache);
     
    var cache = factory.GetCache("default");
  • The configuration way – in the client config file, we we use the localCache
    attribute like in the following example:
    <dcacheClient deployment="simple" localCache="false">
      <hosts>    
        <host name="localhost"
              cachePort="22233"
              cacheHostName="DistributedCacheService" />
      </hosts>
    </dcacheClient> 

Summary

Local cache is a very useful feature of Velocity. It can help to boost the
performance of an application that uses Velocity to new heights.

DotNetKicks Image

Exploring Entity Framework and Data Services Slide Deck

Exploring Entity Framework and Data Services Slide Deck

Yesterday I had a .Net Framework New Logo 
session about Entity Framework
and Data Services in the
Israeli Defense Forces (IDF) .NET
Developers Group
.
As promised, the slide deck and
demos can be downloaded from here.
I want to thank all the participants of the session.

P.S. – a backup of the database that I used in the demos is located in the
Demos directory.
Enjoy.

DotNetKicks Image

New Release for VelocityAdminShell

New Release for VelocityAdminShell

I’ve published a new release for the VelocityAdminShell.
This new release includes a configuration form to enable the configuration
of the shell (instead of doing it manually in the config file).
The following figure shows the current configuration form:
VelocityAdminShellConfigForm

I also changed the look and feel of the shell and added tabs for different operation
types:
VelocityAdminShell

Thanks to Eyal Vardi for the inputs regarding the VelocityAdminShell.
You can download the new release of VelocityAdminShell from here.

DotNetKicks Image