Started implementing static cache provider for the application cache... centralizing static cache.

This commit is contained in:
Shannon Deminick
2013-05-13 19:31:27 -10:00
parent 645637d550
commit 922ebe5411
8 changed files with 425 additions and 92 deletions

View File

@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An abstract class for implementing a cache helper
/// An abstract class for implementing a basic cache provider
/// </summary>
/// <remarks>
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC...
@@ -22,13 +20,5 @@ namespace Umbraco.Core.Cache
public abstract IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith);
public abstract T GetCacheItem<T>(string cacheKey);
public abstract T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
}
}
}

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Core.Cache
/// <summary>
/// A CacheProvider that wraps the logic of the HttpRuntime.Cache
/// </summary>
internal class HttpRuntimeCacheProvider : CacheProviderBase
internal class HttpRuntimeCacheProvider : RuntimeCacheProviderBase
{
private readonly System.Web.Caching.Cache _cache;
private static readonly object Locker = new object();

View File

@@ -5,7 +5,7 @@ using System.Web.Caching;
namespace Umbraco.Core.Cache
{
internal class NullCacheProvider : CacheProviderBase
internal class NullCacheProvider : RuntimeCacheProviderBase
{
public override void ClearAllCache()
{

View File

@@ -0,0 +1,24 @@
using System;
using System.Text;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An abstract class for implementing a runtime cache provider
/// </summary>
/// <remarks>
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC...
/// </remarks>
internal abstract class RuntimeCacheProviderBase : CacheProviderBase
{
public abstract T GetCacheItem<T>(string cacheKey, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// A cache provider that statically caches everything in an in memory dictionary
/// </summary>
internal class StaticCacheProvider : CacheProviderBase
{
private readonly ConcurrentDictionary<string, object> _staticCache = new ConcurrentDictionary<string, object>();
public override void ClearAllCache()
{
_staticCache.Clear();
}
public override void ClearCacheItem(string key)
{
object val;
_staticCache.TryRemove(key, out val);
}
public override void ClearCacheObjectTypes(string typeName)
{
foreach (var key in _staticCache.Keys)
{
if (_staticCache[key] != null
&& _staticCache[key].GetType().ToString().InvariantEquals(typeName))
{
object val;
_staticCache.TryRemove(key, out val);
}
}
}
public override void ClearCacheObjectTypes<T>()
{
foreach (var key in _staticCache.Keys)
{
if (_staticCache[key] != null
&& _staticCache[key].GetType() == typeof(T))
{
object val;
_staticCache.TryRemove(key, out val);
}
}
}
public override void ClearCacheByKeySearch(string keyStartsWith)
{
foreach (var key in _staticCache.Keys)
{
if (key.InvariantStartsWith(keyStartsWith))
{
ClearCacheItem(key);
}
}
}
public override void ClearCacheByKeyExpression(string regexString)
{
foreach (var key in _staticCache.Keys)
{
if (Regex.IsMatch(key, regexString))
{
ClearCacheItem(key);
}
}
}
public override IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
return (from KeyValuePair<string, object> c in _staticCache
where c.Key.InvariantStartsWith(keyStartsWith)
select c.Value.TryConvertTo<T>()
into attempt
where attempt.Success
select attempt.Result).ToList();
}
public override T GetCacheItem<T>(string cacheKey)
{
var result = _staticCache[cacheKey];
if (result == null)
{
return default(T);
}
return result.TryConvertTo<T>().Result;
}
public override T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
{
return (T)_staticCache.GetOrAdd(cacheKey, getCacheItem);
}
}
}

View File

@@ -15,14 +15,13 @@ namespace Umbraco.Core
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
/// <remarks>
/// This class may be opened publicly at some point but needs a review of what is absoletely necessary.
/// </remarks>
public class CacheHelper //: CacheProviderBase
public class CacheHelper
{
private readonly bool _enableCache;
private readonly HttpRuntimeCacheProvider _httpCache;
private readonly NullCacheProvider _nullCache = new NullCacheProvider();
private readonly CacheProviderBase _staticCache;
private readonly CacheProviderBase _nullStaticCache = new NullCacheProvider();
private readonly RuntimeCacheProviderBase _httpCache;
private readonly RuntimeCacheProviderBase _nullHttpCache = new NullCacheProvider();
public CacheHelper(System.Web.Caching.Cache cache)
: this(cache, true)
@@ -30,21 +29,185 @@ namespace Umbraco.Core
}
internal CacheHelper(System.Web.Caching.Cache cache, bool enableCache)
{
_httpCache = new HttpRuntimeCacheProvider(cache);
_enableCache = enableCache;
: this(new HttpRuntimeCacheProvider(cache), enableCache)
{
}
internal CacheHelper(RuntimeCacheProviderBase httpCacheProvider, bool enableCache)
: this(httpCacheProvider, new StaticCacheProvider(), enableCache)
{
}
internal CacheHelper(RuntimeCacheProviderBase httpCacheProvider, CacheProviderBase staticCacheProvider, bool enableCache)
{
_httpCache = httpCacheProvider;
_staticCache = staticCacheProvider;
_enableCache = enableCache;
}
#region Static cache
/// <summary>
/// Clears the item in umbraco's static cache
/// </summary>
internal void ClearAllStaticCache()
{
if (!_enableCache)
{
_nullStaticCache.ClearAllCache();
}
else
{
_staticCache.ClearAllCache();
}
}
/// <summary>
/// Clears the item in umbraco's static cache with the given key
/// </summary>
/// <param name="key">Key</param>
internal void ClearStaticCacheItem(string key)
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheItem(key);
}
else
{
_staticCache.ClearCacheItem(key);
}
}
/// <summary>
/// Clears all objects in the static cache with the System.Type name as the
/// input parameter. (using [object].GetType())
/// </summary>
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
internal void ClearStaticCacheObjectTypes(string typeName)
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheObjectTypes(typeName);
}
else
{
_staticCache.ClearCacheObjectTypes(typeName);
}
}
/// <summary>
/// Clears all objects in the static cache with the System.Type specified
/// </summary>
internal void ClearStaticCacheObjectTypes<T>()
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheObjectTypes<T>();
}
else
{
_staticCache.ClearCacheObjectTypes<T>();
}
}
/// <summary>
/// Clears all static cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
internal void ClearStaticCacheByKeySearch(string keyStartsWith)
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheByKeySearch(keyStartsWith);
}
else
{
_staticCache.ClearCacheByKeySearch(keyStartsWith);
}
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
internal void ClearStaticCacheByKeyExpression(string regexString)
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheByKeyExpression(regexString);
}
else
{
_staticCache.ClearCacheByKeyExpression(regexString);
}
}
internal IEnumerable<T> GetStaticCacheItemsByKeySearch<T>(string keyStartsWith)
{
if (!_enableCache)
{
return _nullStaticCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
else
{
return _staticCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
}
/// <summary>
/// Returns a static cache item by key, does not update the cache if it isn't there.
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <returns></returns>
internal TT GetStaticCacheItem<TT>(string cacheKey)
{
if (!_enableCache)
{
return _nullStaticCache.GetCacheItem<TT>(cacheKey);
}
else
{
return _staticCache.GetCacheItem<TT>(cacheKey);
}
}
/// <summary>
/// Gets (and adds if necessary) an item from the static cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
internal TT GetStaticCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
if (!_enableCache)
{
return _nullStaticCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
else
{
return _staticCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
}
#endregion
#region Runtime/Http Cache
/// <summary>
/// Clears the item in umbraco's runtime cache
/// </summary>
public void ClearAllCache()
{
if (!_enableCache)
{
_nullCache.ClearAllCache();
}
else
{
_httpCache.ClearAllCache();
}
{
if (!_enableCache)
{
_nullHttpCache.ClearAllCache();
}
else
{
_httpCache.ClearAllCache();
}
}
/// <summary>
@@ -55,7 +218,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
_nullCache.ClearCacheItem(key);
_nullHttpCache.ClearCacheItem(key);
}
else
{
@@ -73,7 +236,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
_nullCache.ClearCacheObjectTypes(typeName);
_nullHttpCache.ClearCacheObjectTypes(typeName);
}
else
{
@@ -84,55 +247,55 @@ namespace Umbraco.Core
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
public void ClearCacheObjectTypes<T>()
{
public void ClearCacheObjectTypes<T>()
{
if (!_enableCache)
{
_nullCache.ClearCacheObjectTypes<T>();
_nullHttpCache.ClearCacheObjectTypes<T>();
}
else
{
_httpCache.ClearCacheObjectTypes<T>();
}
}
}
/// <summary>
/// <summary>
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
public void ClearCacheByKeySearch(string keyStartsWith)
{
{
if (!_enableCache)
{
_nullCache.ClearCacheByKeySearch(keyStartsWith);
_nullHttpCache.ClearCacheByKeySearch(keyStartsWith);
}
else
{
_httpCache.ClearCacheByKeySearch(keyStartsWith);
}
}
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
public void ClearCacheByKeyExpression(string regexString)
{
public void ClearCacheByKeyExpression(string regexString)
{
if (!_enableCache)
{
_nullCache.ClearCacheByKeyExpression(regexString);
_nullHttpCache.ClearCacheByKeyExpression(regexString);
}
else
{
_httpCache.ClearCacheByKeyExpression(regexString);
}
}
}
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
if (!_enableCache)
{
return _nullCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
return _nullHttpCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
else
{
@@ -140,7 +303,7 @@ namespace Umbraco.Core
}
}
/// <summary>
/// <summary>
/// Returns a cache item by key, does not update the cache if it isn't there.
/// </summary>
/// <typeparam name="TT"></typeparam>
@@ -150,7 +313,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey);
return _nullHttpCache.GetCacheItem<TT>(cacheKey);
}
else
{
@@ -169,7 +332,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
else
{
@@ -190,7 +353,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, timeout, getCacheItem);
}
else
{
@@ -213,7 +376,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey, refreshAction, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, refreshAction, timeout, getCacheItem);
}
else
{
@@ -237,7 +400,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, timeout, getCacheItem);
}
else
{
@@ -257,15 +420,15 @@ namespace Umbraco.Core
/// <param name="getCacheItem"></param>
/// <returns></returns>
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<TT> getCacheItem)
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<TT> getCacheItem)
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
}
else
{
@@ -289,7 +452,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullCache.GetCacheItem<TT>(cacheKey, priority, null, cacheDependency, null, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, null, cacheDependency, null, getCacheItem);
}
else
{
@@ -310,14 +473,14 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
_nullCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
}
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
@@ -333,7 +496,7 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
_nullCache.InsertCacheItem<T>(cacheKey, priority, timeout, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, timeout, getCacheItem);
}
else
{
@@ -341,30 +504,30 @@ namespace Umbraco.Core
}
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<T> getCacheItem)
{
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<T> getCacheItem)
{
if (!_enableCache)
{
_nullCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
}
}
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
@@ -376,22 +539,23 @@ namespace Umbraco.Core
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
if (!_enableCache)
{
_nullCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
}
}
}
#endregion
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
@@ -10,10 +11,60 @@ using System.Web;
namespace Umbraco.Core
{
///<summary>
/// Extension methods for dictionary
/// Extension methods for dictionary & concurrentdictionary
///</summary>
internal static class DictionaryExtensions
{
/// <summary>
/// Updates an item with the specified key with the specified value
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="dict"></param>
/// <param name="key"></param>
/// <param name="updateFactory"></param>
/// <returns></returns>
/// <remarks>
/// Taken from: http://stackoverflow.com/questions/12240219/is-there-a-way-to-use-concurrentdictionary-tryupdate-with-a-lambda-expression
///
/// If there is an item in the dictionary with the key, it will keep trying to update it until it can
/// </remarks>
public static bool TryUpdate<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TValue, TValue> updateFactory)
{
TValue curValue;
while (dict.TryGetValue(key, out curValue))
{
if (dict.TryUpdate(key, updateFactory(curValue), curValue))
return true;
//if we're looping either the key was removed by another thread, or another thread
//changed the value, so we start again.
}
return false;
}
/// <summary>
/// Updates an item with the specified key with the specified value
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="dict"></param>
/// <param name="key"></param>
/// <param name="updateFactory"></param>
/// <returns></returns>
/// <remarks>
/// Taken from: http://stackoverflow.com/questions/12240219/is-there-a-way-to-use-concurrentdictionary-tryupdate-with-a-lambda-expression
///
/// WARNING: If the value changes after we've retreived it, then the item will not be updated
/// </remarks>
public static bool TryUpdateOptimisitic<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TValue, TValue> updateFactory)
{
TValue curValue;
if (!dict.TryGetValue(key, out curValue))
return false;
dict.TryUpdate(key, updateFactory(curValue), curValue);
return true;//note we return true whether we succeed or not, see explanation below.
}
/// <summary>
/// Converts a dictionary to another type by only using direct casting
/// </summary>

View File

@@ -112,13 +112,15 @@
<Compile Include="Auditing\IAuditWriteProvider.cs" />
<Compile Include="CacheHelper.cs" />
<Compile Include="Cache\CacheKeys.cs" />
<Compile Include="Cache\CacheProviderBase.cs" />
<Compile Include="Cache\CacheRefresherBase.cs" />
<Compile Include="Cache\CacheRefresherEventArgs.cs" />
<Compile Include="Cache\CacheProviderBase.cs" />
<Compile Include="Cache\RuntimeCacheProviderBase.cs" />
<Compile Include="Cache\HttpRuntimeCacheProvider.cs" />
<Compile Include="Cache\IJsonCacheRefresher.cs" />
<Compile Include="Cache\JsonCacheRefresherBase.cs" />
<Compile Include="Cache\NullCacheProvider.cs" />
<Compile Include="Cache\StaticCacheProvider.cs" />
<Compile Include="Cache\TypedCacheRefresherBase.cs" />
<Compile Include="CodeAnnotations\FriendlyNameAttribute.cs" />
<Compile Include="CodeAnnotations\UmbracoObjectTypeAttribute.cs" />