Cache Custom Provider for full integration(design time) ENTLIB 5.0

Topics: Building and extending application blocks, Caching Application Block
Aug 11, 2012 at 2:07 AM

Hi,

I'm implemented ICACHEManager for Memcached  but i need load the configuration settings using full Integration(also called design time). Im following the indications on:

http://msdn.microsoft.com/en-us/library/ff664483%28v=pandp.50%29

The problem emerges in the implementation of the CacheManagerDataBase configuration element base class. I can create the properties but how to get this work? I mean how this reads the configuration from file, any examples ?

There are some virtual methods to overload in that base class.

Aug 11, 2012 at 10:42 AM

If you want full design time integration then you will have to re-create the CacheManagerData class with the appropriate changes to point to your CacheManager class.  It also looks like you will have to re-create the AddCacheManagerCommand class.  Assuming that you also have created a DesignResources.resx with the appropriate strings then the code will look like this (my CacheManager is called MyCacheManager so the naming reflects this):

    public class AddMyCacheManagerCommand : DefaultCollectionElementAddCommand
    {
        CacheManagerSectionViewModel cachingSection;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", Justification = "Validated with Guard class")]
        public AddMyCacheManagerCommand(ElementCollectionViewModel collection, IUIServiceWpf uiService)
            : base(new ConfigurationElementType(typeof(MyCacheManagerData)), collection, uiService)
        {
            Guard.ArgumentNotNull(collection, "collection");

            this.cachingSection = collection.ContainingSection as CacheManagerSectionViewModel;
        }

        protected override void InnerExecute(object parameter)
        {
            base.InnerExecute(parameter);

            AddedElementViewModel.Property("CacheStorage").Value = cachingSection.NullBackingStoreName;
        }
    }

    [ResourceDescription(typeof(DesignResources), "CacheManagerDataDescription")]
    [ResourceDisplayName(typeof(DesignResources), "CacheManagerDataDisplayName")]
    [Command("CachingCustomCacheFullIntegration.AddMyCacheManagerCommand, CachingCustomCacheFullIntegration",
                        Replace = CommandReplacement.DefaultAddCommandReplacement,
                        CommandPlacement = CommandPlacement.ContextAdd)]
    public class MyCacheManagerData : CacheManagerDataBase
    {
        private const string expirationPollFrequencyInSecondsProperty = "expirationPollFrequencyInSeconds";
        private const string maximumElementsInCacheBeforeScavengingProperty = "maximumElementsInCacheBeforeScavenging";
        private const string numberToRemoveWhenScavengingProperty = "numberToRemoveWhenScavenging";
        private const string backingStoreNameProperty = "backingStoreName";

        public MyCacheManagerData()
            : base(typeof(MyCacheManager))
        {
        }

        public MyCacheManagerData(string name, int expirationPollFrequencyInSeconds, int maximumElementsInCacheBeforeScavenging, int numberToRemoveWhenScavenging, string cacheStorage)
            : base(name, typeof(MyCacheManager))
        {
            this.ExpirationPollFrequencyInSeconds = expirationPollFrequencyInSeconds;
            this.MaximumElementsInCacheBeforeScavenging = maximumElementsInCacheBeforeScavenging;
            this.NumberToRemoveWhenScavenging = numberToRemoveWhenScavenging;
            this.CacheStorage = cacheStorage;
        }

        [ConfigurationProperty(expirationPollFrequencyInSecondsProperty, IsRequired = true, DefaultValue = 60)]
        [ResourceDescription(typeof(DesignResources), "CacheManagerDataExpirationPollFrequencyInSecondsDescription")]
        [ResourceDisplayName(typeof(DesignResources), "CacheManagerDataExpirationPollFrequencyInSecondsDisplayName")]
        public int ExpirationPollFrequencyInSeconds
        {
            get { return (int)base[expirationPollFrequencyInSecondsProperty]; }
            set { base[expirationPollFrequencyInSecondsProperty] = value; }
        }

        [ConfigurationProperty(maximumElementsInCacheBeforeScavengingProperty, IsRequired = true, DefaultValue = 1000)]
        [ResourceDescription(typeof(DesignResources), "CacheManagerDataMaximumElementsInCacheBeforeScavengingDescription")]
        [ResourceDisplayName(typeof(DesignResources), "CacheManagerDataMaximumElementsInCacheBeforeScavengingDisplayName")]
        public int MaximumElementsInCacheBeforeScavenging
        {
            get { return (int)base[maximumElementsInCacheBeforeScavengingProperty]; }
            set { base[maximumElementsInCacheBeforeScavengingProperty] = value; }
        }

        [ConfigurationProperty(numberToRemoveWhenScavengingProperty, IsRequired = true, DefaultValue = 10)]
        [ResourceDescription(typeof(DesignResources), "CacheManagerDataNumberToRemoveWhenScavengingDescription")]
        [ResourceDisplayName(typeof(DesignResources), "CacheManagerDataNumberToRemoveWhenScavengingDisplayName")]
        public int NumberToRemoveWhenScavenging
        {
            get { return (int)base[numberToRemoveWhenScavengingProperty]; }
            set { base[numberToRemoveWhenScavengingProperty] = value; }
        }

        [ConfigurationProperty(backingStoreNameProperty, IsRequired = true)]
        [Reference(typeof(NameTypeConfigurationElementCollection<CacheStorageData, CustomCacheStorageData>), typeof(CacheStorageData))]
        [ResourceDescription(typeof(DesignResources), "CacheManagerDataCacheStorageDescription")]
        [ResourceDisplayName(typeof(DesignResources), "CacheManagerDataCacheStorageDisplayName")]
        [ViewModel("Microsoft.Practices.EnterpriseLibrary.Configuration.Design.ViewModel.BlockSpecifics.CacheManagerBackingStoreProperty, Microsoft.Practices.EnterpriseLibrary.Configuration.DesignTime")]
        public string CacheStorage
        {
            get { return (string)base[backingStoreNameProperty]; }
            set { base[backingStoreNameProperty] = value; }
        }

        public override IEnumerable<TypeRegistration> GetRegistrations(IConfigurationSource configurationSource)
        {
            IEnumerable<TypeRegistration> baseRegistrations = base.GetRegistrations(configurationSource);

            return baseRegistrations.Concat(new TypeRegistration[]{ 
                GetBackgroundScheduler(),
                GetExpirationTask(),
                GetScavengerTask(),
                GetExpirationPollTimer(),
                GetInstrumentationProviderRegistration(configurationSource), 
                GetCacheRegistration() });
        }

        protected override Expression<Func<ICacheManager>> GetCacheManagerCreationExpression()
        {
            return () =>
                new MyCacheManager(Container.Resolved<Cache>(Name),
                                  Container.Resolved<BackgroundScheduler>(Name),
                                  Container.Resolved<ExpirationPollTimer>(Name));


        }

        private TypeRegistration GetBackgroundScheduler()
        {
            return new TypeRegistration<BackgroundScheduler>(() => new BackgroundScheduler(
                Container.Resolved<ExpirationTask>(Name),
                Container.Resolved<ScavengerTask>(Name),
                Container.Resolved<ICachingInstrumentationProvider>(Name)))
            {
                Name = this.Name
            };

        }

        private TypeRegistration GetExpirationTask()
        {
            return new TypeRegistration<ExpirationTask>(() => new ExpirationTask(
                Container.Resolved<Cache>(Name),
                Container.Resolved<ICachingInstrumentationProvider>(Name)))
            {
                Name = this.Name
            };
        }

        private TypeRegistration GetScavengerTask()
        {
            return new TypeRegistration<ScavengerTask>(() => new ScavengerTask(
              NumberToRemoveWhenScavenging,
              MaximumElementsInCacheBeforeScavenging,
              Container.Resolved<Cache>(Name),
              Container.Resolved<ICachingInstrumentationProvider>(Name)))
            {
                Name = this.Name
            };
        }

        private TypeRegistration GetExpirationPollTimer()
        {
            return new TypeRegistration<ExpirationPollTimer>(() => new ExpirationPollTimer(ExpirationPollFrequencyInSeconds * 1000))
            {
                Name = this.Name
            };
        }

        private TypeRegistration GetCacheRegistration()
        {
            return new TypeRegistration<Cache>(() => new Cache(
               Container.Resolved<IBackingStore>(CacheStorage),
               Container.Resolved<ICachingInstrumentationProvider>(Name)))
            {
                Name = this.Name
            };
        }

        private TypeRegistration GetInstrumentationProviderRegistration(IConfigurationSource configurationSource)
        {
            var instrumentationSection = InstrumentationConfigurationSection.GetSection(configurationSource);

            return new TypeRegistration<ICachingInstrumentationProvider>(
                () => new CachingInstrumentationProvider(
                    Name,
                    instrumentationSection.PerformanceCountersEnabled,
                    instrumentationSection.EventLoggingEnabled,
                    instrumentationSection.ApplicationInstanceName))
            {
                Name = Name
            };
        }
    }

This assumes that your CacheManager looks similar to the default EntLib Cache Manager; if not you will need to modify to suit your needs (i.e. add or remove properties).  You will also need assembly references to PresentationCore, System.Windows.Forms as well as the Enterprise Library Configuration assemblies.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Aug 22, 2012 at 8:45 PM

Thanks Randy! Very useful information