diff --git a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs b/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs index 90323dbbe2..ea68433904 100644 --- a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs +++ b/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs @@ -68,6 +68,9 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes(string typeName) { + var type = Type.GetType(typeName); + if (type == null) return; + var isInterface = type.IsInterface; using (WriteLock) { foreach (var entry in GetDictionaryEntries() @@ -77,7 +80,10 @@ namespace Umbraco.Core.Cache // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null var value = GetSafeLazyValue((Lazy)x.Value, true); - return value == null || value.GetType().ToString().InvariantEquals(typeName); + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type)); }) .ToArray()) RemoveEntry((string) entry.Key); @@ -87,6 +93,7 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes() { var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; using (WriteLock) { foreach (var entry in GetDictionaryEntries() @@ -98,14 +105,9 @@ namespace Umbraco.Core.Cache // get non-created as NonCreatedValue & exceptions as null var value = GetSafeLazyValue((Lazy)x.Value, true); - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return value == null || - (typeOfT.IsInterface - ? (value is T) - : value.GetType() == typeOfT); + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT)); }) .ToArray()) RemoveEntry((string) entry.Key); @@ -115,6 +117,7 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes(Func predicate) { var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; var plen = CacheItemPrefix.Length + 1; using (WriteLock) { @@ -128,11 +131,9 @@ namespace Umbraco.Core.Cache var value = GetSafeLazyValue((Lazy)x.Value, true); if (value == null) return true; - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return ((typeOfT.IsInterface && value is T) || (value.GetType() == typeOfT)) + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return (isInterface ? (value is T) : (value.GetType() == typeOfT)) // run predicate on the 'public key' part only, ie without prefix && predicate(((string) x.Key).Substring(plen), (T) value); })) diff --git a/src/Umbraco.Core/Cache/ICacheProvider.cs b/src/Umbraco.Core/Cache/ICacheProvider.cs index 6cec619be8..0d2bb1bdb6 100644 --- a/src/Umbraco.Core/Cache/ICacheProvider.cs +++ b/src/Umbraco.Core/Cache/ICacheProvider.cs @@ -8,13 +8,51 @@ namespace Umbraco.Core.Cache /// public interface ICacheProvider { + /// + /// Removes all items from the cache. + /// void ClearAllCache(); + + /// + /// Removes an item from the cache, identified by its key. + /// + /// The key of the item. void ClearCacheItem(string key); + + /// + /// Removes items from the cache, of a specified type. + /// + /// The name of the type to remove. + /// + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). + /// Performs a case-sensitive search. + /// void ClearCacheObjectTypes(string typeName); + + /// + /// Removes items from the cache, of a specified type. + /// + /// The type of the items to remove. + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). void ClearCacheObjectTypes(); + + /// + /// Removes items from the cache, of a specified type, satisfying a predicate. + /// + /// The type of the items to remove. + /// The predicate to satisfy. + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). void ClearCacheObjectTypes(Func predicate); + void ClearCacheByKeySearch(string keyStartsWith); void ClearCacheByKeyExpression(string regexString); + IEnumerable GetCacheItemsByKeySearch(string keyStartsWith); IEnumerable GetCacheItemsByKeyExpression(string regexString); diff --git a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs index 27838ba51a..b85f718cb3 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Reflection; using System.Runtime.Caching; using System.Text.RegularExpressions; using System.Threading; @@ -71,6 +72,9 @@ namespace Umbraco.Core.Cache public virtual void ClearCacheObjectTypes(string typeName) { + var type = Type.GetType(typeName); + if (type == null) return; + var isInterface = type.IsInterface; using (new WriteLock(_locker)) { foreach (var key in MemoryCache @@ -80,7 +84,10 @@ namespace Umbraco.Core.Cache // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null var value = GetSafeLazyValue((Lazy)x.Value, true); - return value == null || value.GetType().ToString().InvariantEquals(typeName); + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type)); }) .Select(x => x.Key) .ToArray()) // ToArray required to remove @@ -93,6 +100,7 @@ namespace Umbraco.Core.Cache using (new WriteLock(_locker)) { var typeOfT = typeof (T); + var isInterface = typeOfT.IsInterface; foreach (var key in MemoryCache .Where(x => { @@ -101,14 +109,9 @@ namespace Umbraco.Core.Cache // get non-created as NonCreatedValue & exceptions as null var value = GetSafeLazyValue((Lazy)x.Value, true); - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return value == null || - (typeOfT.IsInterface - ? (value is T) - : value.GetType() == typeOfT); + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT)); }) .Select(x => x.Key) @@ -122,6 +125,7 @@ namespace Umbraco.Core.Cache using (new WriteLock(_locker)) { var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; foreach (var key in MemoryCache .Where(x => { @@ -131,11 +135,9 @@ namespace Umbraco.Core.Cache var value = GetSafeLazyValue((Lazy)x.Value, true); if (value == null) return true; - //TODO: waiting on a response for this comment: https://github.com/umbraco/Umbraco-CMS/commit/c2db7b2b9b78847a828512818e79492ecc24ac7c#commitcomment-9492329 - // until then we will check if 'T' is an interface and if so we will use the 'is' clause, - // otherwise we do an exact match. - - return ((typeOfT.IsInterface && value is T) || (value.GetType() == typeOfT)) + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return (isInterface ? (value is T) : (value.GetType() == typeOfT)) && predicate(x.Key, (T)value); }) .Select(x => x.Key)