Commits

Anonymous committed f7d61cc Draft

added new Cineraria.Caching assembly with MemCache<T> class

  • Participants
  • Parent commits d84f8d8

Comments (0)

Files changed (6)

File Cineraria.Caching/Cineraria.Caching.csproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Cineraria.Caching</RootNamespace>
+    <AssemblyName>Cineraria.Caching</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <DocumentationFile>bin\Debug\Cineraria.Caching.XML</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>Cineraria.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Runtime.Caching" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GlobalSuppressions.cs" />
+    <Compile Include="MemCache.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Cineraria.Convenience\Cineraria.Convenience.csproj">
+      <Project>{EEE8C93C-4F05-430F-85AA-0D4E8C508F7B}</Project>
+      <Name>Cineraria.Convenience</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Cineraria.pfx" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

File Cineraria.Caching/GlobalSuppressions.cs

+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mem", Scope = "type", Target = "Shana.MemCache`1")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1", Scope = "member", Target = "Shana.MemCache`1.#GetOrInsert(System.String,System.Func`1<!0>)")]

File Cineraria.Caching/MemCache.cs

+// -----------------------------------------------------------------------
+// <copyright file="MemCache.cs">
+//     Copyright (c) Rhys 2012-06-10. All rights reserved.
+// </copyright>
+// -----------------------------------------------------------------------
+
+namespace Shana
+{
+    using System;
+    using System.Collections.Specialized;
+    using System.Runtime.Caching;
+
+    using Cineraria.Convenience;
+
+    /// <summary>
+    /// The result of a <see cref="MemCache&lt;T&gt;"/> query.
+    /// </summary>
+    /// <typeparam name="T">The type of object stored in the cache.</typeparam>
+    public struct MemoryCacheResult<T>
+    {
+        /// <summary>
+        /// Gets a value indicating whether the request returned a value.
+        /// </summary>
+        public bool Exists { get; internal set; }
+
+        /// <summary>
+        /// Gets the result of the request. Only valid if <see cref="Exists"/>
+        /// is true.
+        /// </summary>
+        public T Value { get; internal set; }
+    }
+
+    /// <summary>
+    /// An in-memory object cache.
+    /// </summary>
+    /// <typeparam name="T">The type of object stored in the cache.</typeparam>
+    public class MemCache<T> : IDisposable where T : class
+    {
+        /// <summary>
+        /// The object used to represent null in the cache.
+        /// </summary>
+        private static readonly object _fakeNull = new object();
+
+        /// <summary>
+        /// Empty cache item policy to pass when required.
+        /// </summary>
+        private static readonly CacheItemPolicy _policy = new CacheItemPolicy();
+
+        /// <summary>
+        /// The underlying cache.
+        /// </summary>
+        private readonly System.Runtime.Caching.MemoryCache _cache;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MemCache&lt;T&gt;"/>.
+        /// </summary>
+        /// <param name="name">
+        /// The name to pass to the underlying <see cref="MemoryCache"/> to
+        /// look up configuration information if needed.
+        /// </param>
+        /// <param name="pollingInterval">
+        /// The time interval between each pruning of this instance to below
+        /// its memory limit, in "HH:MM:SS" string format.
+        /// </param>
+        /// <param name="maxMegabytes">
+        /// The maximum memory limit of this instance in megabytes.
+        /// </param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// <paramref name="maxMegabytes"/> cannot be negative.
+        /// </exception>
+        /// <exception cref="ArgumentNullException">
+        /// Neither <paramref name="name"/> nor
+        /// <paramref name="pollingInterval"/> can be null.
+        /// </exception>
+        public MemCache(string name, string pollingInterval, int maxMegabytes)
+        {
+            pollingInterval.ThrowIfNull("pollingInterval");
+            if (maxMegabytes < 0)
+            {
+                throw new ArgumentOutOfRangeException(
+                    "maxMegabytes", "maxMegabytes cannot be negative");
+            }
+
+            var config = new NameValueCollection();
+            config.Add("pollingInterval", pollingInterval);
+            config.Add("physicalMemoryLimitPercentage", "0");
+            config.Add(
+                "cacheMemoryLimitMegabytes",
+                maxMegabytes.ToStringInvariant());
+
+            this._cache = new MemoryCache(name, config);
+        }
+
+        /// <summary>
+        /// Inserts an entry into the cache using a key.
+        /// </summary>
+        /// <param name="key">A unique identifier for the cache entry.</param>
+        /// <param name="value">The value to insert.</param>
+        public void Set(string key, T value)
+        {
+            this.SetWithReplacement(key, value);
+        }
+
+        /// <summary>
+        /// Returns an entry from the cache.
+        /// </summary>
+        /// <param name="key">
+        /// A unique identifier for the cache entry to get.
+        /// </param>
+        /// <returns>
+        /// A reference to the cache entry that is identified by
+        /// <paramref name="key"/>, or null if no such entry exists.
+        /// </returns>
+        public T Get(string key)
+        {
+            return this.GetEntry(key).Value;
+        }
+
+        /// <summary>
+        /// Returns an entry from the cache.
+        /// </summary>
+        /// <param name="key">
+        /// A unique identifier for the cache entry to get.
+        /// </param>
+        /// <returns>
+        /// A <see cref="MemoryCacheResult&lt;T&gt;"/> containing a reference to
+        /// the cache entry that is identified by <paramref name="key"/>.
+        /// </returns>
+        public MemoryCacheResult<T> GetEntry(string key)
+        {
+            object result = this._cache.Get(key);
+            if (null == result)
+            {
+                return new MemoryCacheResult<T> { Exists = false, Value = null };
+            }
+            else
+            {
+                if (object.ReferenceEquals(result, MemCache<T>._fakeNull))
+                {
+                    result = null;
+                }
+
+                return new MemoryCacheResult<T>
+                {
+                    Exists = true,
+                    Value = (T)result
+                };
+            }
+        }
+
+        /// <summary>
+        /// Gets an entry from the cache or inserts a new entry using the
+        /// specified generator if no such entry exists.
+        /// </summary>
+        /// <param name="key">
+        /// A unique identifier for the cache entry to get.
+        /// </param>
+        /// <param name="generator">
+        /// A function that returns the value of the entry to set. Called only
+        /// if there is no existing entry with the specified key.
+        /// </param>
+        /// <returns>
+        /// A reference to the cache entry that is identified by
+        /// <paramref name="key"/>.
+        /// </returns>
+        /// <exception cref="ArgumentNullException">
+        /// generator cannot be null.
+        /// </exception>
+        public T GetOrInsert(string key, Func<T> generator)
+        {
+            generator.ThrowIfNull("generator");
+
+            MemoryCacheResult<T> entry = this.GetEntry(key);
+            if (!entry.Exists)
+            {
+                entry.Value = generator();
+                this.SetWithReplacement(key, entry.Value);
+                entry.Exists = true;
+            }
+
+            return (T)entry.Value;
+        }
+
+        /// <summary>
+        /// Removes an entry from the cache.
+        /// </summary>
+        /// <param name="key">
+        /// A unique identifier for the cache entry to remove.
+        /// </param>
+        public void Remove(string key)
+        {
+            this._cache.Remove(key);
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing,
+        /// releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            this.Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposeManaged">
+        /// <c>true</c> to release both managed and unmanaged resources;
+        /// <c>false</c> to release only unmanaged resources.
+        /// </param>
+        protected virtual void Dispose(bool disposeManaged)
+        {
+            if (disposeManaged)
+            {
+                this._cache.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Sets a cache entry value, replacing a null value with
+        /// <see cref="_fakeNull"/>.
+        /// </summary>
+        /// <param name="key">
+        /// A unique identifier for the cache entry to set.
+        /// </param>
+        /// <param name="value">The value to set.</param>
+        private void SetWithReplacement(string key, object value)
+        {
+            this._cache.Set(
+                key,
+                value ?? MemCache<T>._fakeNull,
+                MemCache<T>._policy);
+        }
+    }
+}

File Cineraria.Caching/Properties/AssemblyInfo.cs

+//<auto-generated/>
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Cineraria.Caching")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Cineraria.Caching")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c6d407e1-36d1-496a-afb7-f7ac934e17d6")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: CLSCompliant(true)]

File Cineraria.Caching/Settings.StyleCop

+<StyleCopSettings Version="105">
+  <Analyzers>
+    <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
+      <Rules>
+        <Rule Name="FileHeaderMustHaveValidCompanyText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+    <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
+      <Rules>
+        <Rule Name="FieldNamesMustNotBeginWithUnderscore">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+  </Analyzers>
+</StyleCopSettings>

File Cineraria.sln

 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cineraria.Concurrency.Buffers", "Cineraria.Concurrency.Buffers\Cineraria.Concurrency.Buffers.csproj", "{DFECC723-4D48-494F-854F-553274E7725C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cineraria.Caching", "Cineraria.Caching\Cineraria.Caching.csproj", "{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		{DFECC723-4D48-494F-854F-553274E7725C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
 		{DFECC723-4D48-494F-854F-553274E7725C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 		{DFECC723-4D48-494F-854F-553274E7725C}.Release|x86.ActiveCfg = Release|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{75F0C3FE-97A3-41E2-AED3-D8B617A8E3B8}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE