2016-05-18 23:34:56 +02:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Web ;
using System.Web.Caching ;
namespace Umbraco.Core.Cache
{
2017-07-20 11:21:28 +02:00
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
2016-05-18 23:34:56 +02:00
public class CacheHelper
2017-07-20 11:21:28 +02:00
{
2016-05-18 23:34:56 +02:00
private static readonly ICacheProvider NullRequestCache = new NullCacheProvider ();
private static readonly ICacheProvider NullStaticCache = new NullCacheProvider ();
private static readonly IRuntimeCacheProvider NullRuntimeCache = new NullCacheProvider ();
2017-05-12 14:49:44 +02:00
private static readonly IsolatedRuntimeCache NullIsolatedCache = new IsolatedRuntimeCache ( _ => NullRuntimeCache );
2017-07-20 11:21:28 +02:00
public static CacheHelper NoCache { get ; } = new CacheHelper ( NullRuntimeCache , NullStaticCache , NullRequestCache , NullIsolatedCache );
2017-05-12 14:49:44 +02:00
2017-07-20 11:21:28 +02:00
/// <summary>
2016-05-18 23:34:56 +02:00
/// Creates a cache helper with disabled caches
/// </summary>
/// <returns></returns>
/// <remarks>
/// Good for unit testing
/// </remarks>
public static CacheHelper CreateDisabledCacheHelper ()
{
2017-05-12 14:49:44 +02:00
// do *not* return NoCache
// NoCache is a special instance that is detected by RepositoryBase and disables all cache policies
// CreateDisabledCacheHelper is used in tests to use no cache, *but* keep all cache policies
return new CacheHelper ( NullRuntimeCache , NullStaticCache , NullRequestCache , NullIsolatedCache );
2016-05-18 23:34:56 +02:00
}
2017-07-20 11:21:28 +02:00
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
public CacheHelper ()
: this (
new HttpRuntimeCacheProvider ( HttpRuntime . Cache ),
new StaticCacheProvider (),
2016-05-18 23:34:56 +02:00
new HttpRequestCacheProvider (),
new IsolatedRuntimeCache ( t => new ObjectCacheRuntimeCacheProvider ()))
2017-07-20 11:21:28 +02:00
{
2016-05-18 23:34:56 +02:00
}
2017-07-20 11:21:28 +02:00
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
/// <param name="cache"></param>
public CacheHelper ( System . Web . Caching . Cache cache )
: this (
new HttpRuntimeCacheProvider ( cache ),
new StaticCacheProvider (),
new HttpRequestCacheProvider (),
new IsolatedRuntimeCache ( t => new ObjectCacheRuntimeCacheProvider ()))
{
}
[Obsolete("Use the constructor the specifies all dependencies")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CacheHelper (
IRuntimeCacheProvider httpCacheProvider ,
ICacheProvider staticCacheProvider ,
ICacheProvider requestCacheProvider )
: this ( httpCacheProvider , staticCacheProvider , requestCacheProvider , new IsolatedRuntimeCache ( t => new ObjectCacheRuntimeCacheProvider ()))
{
}
/// <summary>
/// Initializes a new instance based on the provided providers
/// </summary>
/// <param name="httpCacheProvider"></param>
/// <param name="staticCacheProvider"></param>
/// <param name="requestCacheProvider"></param>
/// <param name="isolatedCacheManager"></param>
public CacheHelper (
2016-05-18 23:34:56 +02:00
IRuntimeCacheProvider httpCacheProvider ,
ICacheProvider staticCacheProvider ,
ICacheProvider requestCacheProvider ,
2017-07-20 11:21:28 +02:00
IsolatedRuntimeCache isolatedCacheManager )
2016-05-18 23:34:56 +02:00
{
2017-07-20 11:21:28 +02:00
if ( httpCacheProvider == null ) throw new ArgumentNullException ( "httpCacheProvider" );
if ( staticCacheProvider == null ) throw new ArgumentNullException ( "staticCacheProvider" );
if ( requestCacheProvider == null ) throw new ArgumentNullException ( "requestCacheProvider" );
if ( isolatedCacheManager == null ) throw new ArgumentNullException ( "isolatedCacheManager" );
RuntimeCache = httpCacheProvider ;
2016-05-18 23:34:56 +02:00
StaticCache = staticCacheProvider ;
RequestCache = requestCacheProvider ;
IsolatedRuntimeCache = isolatedCacheManager ;
}
/// <summary>
/// Returns the current Request cache
/// </summary>
public ICacheProvider RequestCache { get ; internal set ; }
2017-07-20 11:21:28 +02:00
2016-05-18 23:34:56 +02:00
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public ICacheProvider StaticCache { get ; internal set ; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
2017-07-20 11:21:28 +02:00
public IRuntimeCacheProvider RuntimeCache { get ; internal set ; }
2016-05-18 23:34:56 +02:00
/// <summary>
/// Returns the current Isolated Runtime cache manager
/// </summary>
public IsolatedRuntimeCache IsolatedRuntimeCache { get ; internal set ; }
#region Legacy Runtime / Http Cache accessors
/// <summary>
/// Clears the item in umbraco's runtime cache
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearAllCache ()
{
RuntimeCache . ClearAllCache ();
IsolatedRuntimeCache . ClearAllCaches ();
}
/// <summary>
2017-07-20 11:21:28 +02:00
/// Clears the item in umbraco's runtime cache with the given key
2016-05-18 23:34:56 +02:00
/// </summary>
/// <param name="key">Key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheItem ( string key )
{
RuntimeCache . ClearCacheItem ( key );
}
/// <summary>
/// Clears all objects in the System.Web.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>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes ( string typeName )
{
RuntimeCache . ClearCacheObjectTypes ( typeName );
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheObjectTypes < T >()
{
RuntimeCache . ClearCacheObjectTypes < T >();
}
/// <summary>
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeySearch ( string keyStartsWith )
{
RuntimeCache . ClearCacheByKeySearch ( keyStartsWith );
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeyExpression ( string regexString )
{
RuntimeCache . ClearCacheByKeyExpression ( regexString );
}
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable < T > GetCacheItemsByKeySearch < T >( string keyStartsWith )
{
return RuntimeCache . GetCacheItemsByKeySearch < T >( keyStartsWith );
}
/// <summary>
/// Returns a 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>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem < TT >( string cacheKey )
{
return RuntimeCache . GetCacheItem < TT >( cacheKey );
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem < TT >( string cacheKey , Func < TT > getCacheItem )
{
return RuntimeCache . GetCacheItem < TT >( cacheKey , getCacheItem );
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem < TT >( string cacheKey ,
TimeSpan timeout , Func < TT > getCacheItem )
{
return RuntimeCache . GetCacheItem < TT >( cacheKey , getCacheItem , timeout );
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem < TT >( string cacheKey ,
CacheItemRemovedCallback refreshAction , TimeSpan timeout ,
Func < TT > getCacheItem )
{
return RuntimeCache . GetCacheItem < TT >( cacheKey , getCacheItem , timeout , removedCallback : refreshAction );
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem < TT >( string cacheKey ,
CacheItemPriority priority , CacheItemRemovedCallback refreshAction , TimeSpan timeout ,
Func < TT > getCacheItem )
{
return RuntimeCache . GetCacheItem < TT >( cacheKey , getCacheItem , timeout , false , priority , refreshAction );
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem < TT >( string cacheKey ,
CacheItemPriority priority ,
CacheItemRemovedCallback refreshAction ,
CacheDependency cacheDependency ,
TimeSpan timeout ,
Func < TT > getCacheItem )
{
var cache = GetHttpRuntimeCacheProvider ( RuntimeCache );
if ( cache != null )
{
var result = cache . GetCacheItem ( cacheKey , () => getCacheItem (), timeout , false , priority , refreshAction , cacheDependency );
return result == null ? default ( TT ) : result . TryConvertTo < TT >(). Result ;
}
throw new InvalidOperationException ( "Cannot use this obsoleted overload when the current provider is not of type " + typeof ( HttpRuntimeCacheProvider ));
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem < TT >( string cacheKey ,
CacheItemPriority priority ,
CacheDependency cacheDependency ,
Func < TT > getCacheItem )
{
var cache = GetHttpRuntimeCacheProvider ( RuntimeCache );
if ( cache != null )
{
var result = cache . GetCacheItem ( cacheKey , () => getCacheItem (), null , false , priority , null , cacheDependency );
return result == null ? default ( TT ) : result . TryConvertTo < TT >(). Result ;
}
throw new InvalidOperationException ( "Cannot use this obsoleted overload when the current provider is not of type " + typeof ( HttpRuntimeCacheProvider ));
}
/// <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="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem < T >( string cacheKey ,
CacheItemPriority priority ,
Func < T > getCacheItem )
{
RuntimeCache . InsertCacheItem < T >( cacheKey , getCacheItem , priority : priority );
}
/// <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="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem < T >( string cacheKey ,
CacheItemPriority priority ,
TimeSpan timeout ,
Func < T > getCacheItem )
{
RuntimeCache . InsertCacheItem < T >( cacheKey , getCacheItem , timeout , priority : priority );
}
/// <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>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem < T >( string cacheKey ,
CacheItemPriority priority ,
CacheDependency cacheDependency ,
TimeSpan timeout ,
Func < T > getCacheItem )
{
var cache = GetHttpRuntimeCacheProvider ( RuntimeCache );
if ( cache != null )
{
cache . InsertCacheItem ( cacheKey , () => getCacheItem (), timeout , false , priority , null , cacheDependency );
}
throw new InvalidOperationException ( "Cannot use this obsoleted overload when the current provider is not of type " + typeof ( HttpRuntimeCacheProvider ));
}
/// <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="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem < T >( string cacheKey ,
CacheItemPriority priority ,
CacheItemRemovedCallback refreshAction ,
CacheDependency cacheDependency ,
TimeSpan ? timeout ,
Func < T > getCacheItem )
{
var cache = GetHttpRuntimeCacheProvider ( RuntimeCache );
if ( cache != null )
{
cache . InsertCacheItem ( cacheKey , () => getCacheItem (), timeout , false , priority , refreshAction , cacheDependency );
}
throw new InvalidOperationException ( "Cannot use this obsoleted overload when the current provider is not of type " + typeof ( HttpRuntimeCacheProvider ));
2017-07-20 11:21:28 +02:00
}
2016-05-18 23:34:56 +02:00
#endregion
2017-07-20 11:21:28 +02:00
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider ( IRuntimeCacheProvider runtimeCache )
{
HttpRuntimeCacheProvider cache ;
2016-05-18 23:34:56 +02:00
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper ;
2017-07-20 11:21:28 +02:00
if ( wrapper != null )
{
cache = wrapper . InnerProvider as HttpRuntimeCacheProvider ;
}
else
{
2016-05-18 23:34:56 +02:00
cache = RuntimeCache as HttpRuntimeCacheProvider ;
}
2017-07-20 11:21:28 +02:00
return cache ;
}
2016-05-18 23:34:56 +02:00
}
}