cachingenterprise-libraryextending

Extending Enterprise Library Caching Block - how to get instance of MyCacheManager?


Since the default implementation of CacheManager doesn't provide GetItemsOfType<> (and many others) I thought of building my own:

[ConfigurationElementType(typeof(CustomCacheManagerData))]
public class MyCacheManager : ICacheManager
{
    //The same constructor as in CacheAppBlock - CacheManager, but it's public here:
    public MyCacheManager(Cache realCache, BackgroundScheduler scheduler, ExpirationPollTimer pollTimer)
    {
       this.realCache = realCache;
       this.scheduler = scheduler;
       this.pollTimer = pollTimer;
    }
    //the other code is basically copy/paste from CacheManager in EntLib, with some of my methods like:
    public T[] GetItemsOfType<T>()
    {
        return realCache.CurrentCacheState.Values.OfType<T>().ToArray();
    }
    //I also have some other custom code on the underlying Hashtable in realCache
}

The cofiguration part (the type part points to my class, encryption isn't used):

<cachingConfiguration defaultCacheManager="SomeCacheManager">
    <cacheManagers>
      <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
        numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
        type="MyNamespace.MyCacheManager, MyNamespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
        name="SomeCacheManager" />
</cacheManagers>
    <backingStores>
      <add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        name="Null Storage" />
    </backingStores>
  </cachingConfiguration>

The problem I'm facing now is how to create MyCacheManager? The:

mCityCacheManager = (MyCacheManager)CacheFactory.GetCacheManager("SomeCacheManager");

throws exception saying there's no Constructor in MyCacheManager (but there is, same as in EntLib's CacheManager only they are public in my class...)


Solution

  • That's because MyCacheManager isn't exactly like the EntLib one! And I don't mean the extra methods. Take a look at the declarations.

    Original CacheManager:

    [ConfigurationElementType(typeof(CacheManagerData))]
    public class CacheManager : IDisposable, ICacheManager
    

    MyCacheManager:

    [ConfigurationElementType(typeof(CustomCacheManagerData))]
    public class MyCacheManager : ICacheManager
    

    Other than the name difference (and you didn't extend IDisposable), notice the element type attributes.

    You're using (you have to) the Custom one. The custom one requires a constructor that takes a NameValueCollection as a parameter.

    public MyCacheManager(NameValueCollection collection)
    

    It is a generic configuration driver, so to speak, and as such it cannot be expected to know to create your instance with a 3 parameter constructor consisting of a Cache object, scheduler, and poll timer like you've got. Instead, it passes in these values (or anything you've got set as attributes in the configuration file) via a basic NameValueCollection which you'll have to parse manually.

    See also: Create a custom caching manager for Enterprise Library 4