Merge pull request #1913 from gterdem/pr/1900

Added IDistributedCache<TCacheItem, TCacheKey>
pull/1957/head
Halil İbrahim Kalkan 5 years ago committed by GitHub
commit 82c01a4c95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -21,6 +21,7 @@ namespace Volo.Abp.Caching
context.Services.AddDistributedMemoryCache(); context.Services.AddDistributedMemoryCache();
context.Services.AddSingleton(typeof(IDistributedCache<>), typeof(DistributedCache<>)); context.Services.AddSingleton(typeof(IDistributedCache<>), typeof(DistributedCache<>));
context.Services.AddSingleton(typeof(IDistributedCache<,>), typeof(DistributedCache<,>));
context.Services.Configure<AbpDistributedCacheOptions>(cacheOptions => context.Services.Configure<AbpDistributedCacheOptions>(cacheOptions =>
{ {

@ -15,10 +15,36 @@ namespace Volo.Abp.Caching
/// Represents a distributed cache of <typeparamref name="TCacheItem" /> type. /// Represents a distributed cache of <typeparamref name="TCacheItem" /> type.
/// </summary> /// </summary>
/// <typeparam name="TCacheItem">The type of cache item being cached.</typeparam> /// <typeparam name="TCacheItem">The type of cache item being cached.</typeparam>
public class DistributedCache<TCacheItem> : IDistributedCache<TCacheItem> public class DistributedCache<TCacheItem> : DistributedCache<TCacheItem, string>, IDistributedCache<TCacheItem>
where TCacheItem : class where TCacheItem : class
{ {
public ILogger<DistributedCache<TCacheItem>> Logger { get; set; } public DistributedCache(
IOptions<CacheOptions> cacheOption,
IOptions<DistributedCacheOptions> distributedCacheOption,
IDistributedCache cache,
ICancellationTokenProvider cancellationTokenProvider,
IDistributedCacheSerializer serializer,
ICurrentTenant currentTenant) : base(
cacheOption: cacheOption,
distributedCacheOption: distributedCacheOption,
cache: cache,
cancellationTokenProvider: cancellationTokenProvider,
serializer: serializer,
currentTenant: currentTenant)
{
}
}
/// <summary>
/// Represents a distributed cache of <typeparamref name="TCacheItem" /> type.
/// Uses a generic cache key type of <typeparamref name="TCacheKey" /> type.
/// </summary>
/// <typeparam name="TCacheItem">The type of cache item being cached.</typeparam>
/// <typeparam name="TCacheKey">The type of cache key being used.</typeparam>
public class DistributedCache<TCacheItem, TCacheKey> : IDistributedCache<TCacheItem, TCacheKey>
where TCacheItem : class
{
public ILogger<DistributedCache<TCacheItem, TCacheKey>> Logger { get; set; }
protected string CacheName { get; set; } protected string CacheName { get; set; }
@ -52,7 +78,7 @@ namespace Volo.Abp.Caching
_cacheOption = cacheOption.Value; _cacheOption = cacheOption.Value;
Cache = cache; Cache = cache;
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
Logger = NullLogger<DistributedCache<TCacheItem>>.Instance; Logger = NullLogger<DistributedCache<TCacheItem, TCacheKey>>.Instance;
Serializer = serializer; Serializer = serializer;
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
@ -60,7 +86,41 @@ namespace Volo.Abp.Caching
SetDefaultOptions(); SetDefaultOptions();
} }
protected virtual string NormalizeKey(TCacheKey key)
{
var normalizedKey = "c:" + CacheName + ",k:" + _cacheOption.KeyPrefix + key.ToString();
if (!IgnoreMultiTenancy && CurrentTenant.Id.HasValue)
{
normalizedKey = "t:" + CurrentTenant.Id.Value + "," + normalizedKey;
}
return normalizedKey;
}
protected virtual DistributedCacheEntryOptions GetDefaultCacheEntryOptions()
{
foreach (var configure in _cacheOption.CacheConfigurators)
{
var options = configure.Invoke(CacheName);
if (options != null)
{
return options;
}
}
return _cacheOption.GlobalCacheEntryOptions;
}
protected virtual void SetDefaultOptions()
{
CacheName = CacheNameAttribute.GetCacheName(typeof(TCacheItem));
//IgnoreMultiTenancy
IgnoreMultiTenancy = typeof(TCacheItem).IsDefined(typeof(IgnoreMultiTenancyAttribute), true);
//Configure default cache entry options
DefaultCacheOptions = GetDefaultCacheEntryOptions();
}
/// <summary> /// <summary>
/// Gets a cache item with the given key. If no cache item is found for the given key then returns null. /// Gets a cache item with the given key. If no cache item is found for the given key then returns null.
/// </summary> /// </summary>
@ -68,7 +128,7 @@ namespace Volo.Abp.Caching
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
/// <returns>The cache item, or null.</returns> /// <returns>The cache item, or null.</returns>
public virtual TCacheItem Get( public virtual TCacheItem Get(
string key, TCacheKey key,
bool? hideErrors = null) bool? hideErrors = null)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -106,8 +166,8 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The cache item, or null.</returns> /// <returns>The cache item, or null.</returns>
public virtual async Task<TCacheItem> GetAsync( public virtual async Task<TCacheItem> GetAsync(
string key, TCacheKey key,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default) CancellationToken token = default)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -131,7 +191,7 @@ namespace Volo.Abp.Caching
throw; throw;
} }
if (cachedBytes == null) if (cachedBytes == null)
{ {
return null; return null;
@ -139,7 +199,6 @@ namespace Volo.Abp.Caching
return Serializer.Deserialize<TCacheItem>(cachedBytes); return Serializer.Deserialize<TCacheItem>(cachedBytes);
} }
/// <summary> /// <summary>
/// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item
/// provided by <paramref name="factory" /> delegate and returns the provided cache item. /// provided by <paramref name="factory" /> delegate and returns the provided cache item.
@ -149,10 +208,10 @@ namespace Volo.Abp.Caching
/// <param name="optionsFactory">The cache options for the factory delegate.</param> /// <param name="optionsFactory">The cache options for the factory delegate.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
/// <returns>The cache item.</returns> /// <returns>The cache item.</returns>
public TCacheItem GetOrAdd( public virtual TCacheItem GetOrAdd(
string key, TCacheKey key,
Func<TCacheItem> factory, Func<TCacheItem> factory,
Func<DistributedCacheEntryOptions> optionsFactory = null, Func<DistributedCacheEntryOptions> optionsFactory = null,
bool? hideErrors = null) bool? hideErrors = null)
{ {
var value = Get(key, hideErrors); var value = Get(key, hideErrors);
@ -175,7 +234,6 @@ namespace Volo.Abp.Caching
return value; return value;
} }
/// <summary> /// <summary>
/// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item
/// provided by <paramref name="factory" /> delegate and returns the provided cache item. /// provided by <paramref name="factory" /> delegate and returns the provided cache item.
@ -186,11 +244,11 @@ namespace Volo.Abp.Caching
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The cache item.</returns> /// <returns>The cache item.</returns>
public async Task<TCacheItem> GetOrAddAsync( public virtual async Task<TCacheItem> GetOrAddAsync(
string key, TCacheKey key,
Func<Task<TCacheItem>> factory, Func<Task<TCacheItem>> factory,
Func<DistributedCacheEntryOptions> optionsFactory = null, Func<DistributedCacheEntryOptions> optionsFactory = null,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default) CancellationToken token = default)
{ {
token = CancellationTokenProvider.FallbackToProvider(token); token = CancellationTokenProvider.FallbackToProvider(token);
@ -214,7 +272,6 @@ namespace Volo.Abp.Caching
return value; return value;
} }
/// <summary> /// <summary>
/// Sets the cache item value for the provided key. /// Sets the cache item value for the provided key.
/// </summary> /// </summary>
@ -223,9 +280,9 @@ namespace Volo.Abp.Caching
/// <param name="options">The cache options for the value.</param> /// <param name="options">The cache options for the value.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
public virtual void Set( public virtual void Set(
string key, TCacheKey key,
TCacheItem value, TCacheItem value,
DistributedCacheEntryOptions options = null, DistributedCacheEntryOptions options = null,
bool? hideErrors = null) bool? hideErrors = null)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -249,7 +306,6 @@ namespace Volo.Abp.Caching
throw; throw;
} }
} }
/// <summary> /// <summary>
/// Sets the cache item value for the provided key. /// Sets the cache item value for the provided key.
/// </summary> /// </summary>
@ -260,10 +316,10 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns> /// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
public virtual async Task SetAsync( public virtual async Task SetAsync(
string key, TCacheKey key,
TCacheItem value, TCacheItem value,
DistributedCacheEntryOptions options = null, DistributedCacheEntryOptions options = null,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default) CancellationToken token = default)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -288,15 +344,14 @@ namespace Volo.Abp.Caching
throw; throw;
} }
} }
/// <summary> /// <summary>
/// Refreshes the cache value of the given key, and resets its sliding expiration timeout. /// Refreshes the cache value of the given key, and resets its sliding expiration timeout.
/// </summary> /// </summary>
/// <param name="key">The key of cached item to be retrieved from the cache.</param> /// <param name="key">The key of cached item to be retrieved from the cache.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
public virtual void Refresh( public virtual void Refresh(
string key, TCacheKey key, bool?
bool? hideErrors = null) hideErrors = null)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -315,7 +370,6 @@ namespace Volo.Abp.Caching
throw; throw;
} }
} }
/// <summary> /// <summary>
/// Refreshes the cache value of the given key, and resets its sliding expiration timeout. /// Refreshes the cache value of the given key, and resets its sliding expiration timeout.
/// </summary> /// </summary>
@ -324,8 +378,8 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns> /// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
public virtual async Task RefreshAsync( public virtual async Task RefreshAsync(
string key, TCacheKey key,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default) CancellationToken token = default)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -345,15 +399,13 @@ namespace Volo.Abp.Caching
throw; throw;
} }
} }
/// <summary> /// <summary>
/// Removes the cache item for given key from cache. /// Removes the cache item for given key from cache.
/// </summary> /// </summary>
/// <param name="key">The key of cached item to be retrieved from the cache.</param> /// <param name="key">The key of cached item to be retrieved from the cache.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
public virtual void Remove( public virtual void Remove(
string key, TCacheKey key,
bool? hideErrors = null) bool? hideErrors = null)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -372,7 +424,6 @@ namespace Volo.Abp.Caching
throw; throw;
} }
} }
/// <summary> /// <summary>
/// Removes the cache item for given key from cache. /// Removes the cache item for given key from cache.
/// </summary> /// </summary>
@ -381,8 +432,8 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns> /// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
public virtual async Task RemoveAsync( public virtual async Task RemoveAsync(
string key, TCacheKey key,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default) CancellationToken token = default)
{ {
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
@ -401,42 +452,8 @@ namespace Volo.Abp.Caching
throw; throw;
} }
} }
protected virtual string NormalizeKey(string key) }
{
var normalizedKey = "c:" + CacheName + ",k:" + _cacheOption.KeyPrefix + key;
if (!IgnoreMultiTenancy && CurrentTenant.Id.HasValue)
{
normalizedKey = "t:" + CurrentTenant.Id.Value + "," + normalizedKey;
}
return normalizedKey;
}
protected virtual DistributedCacheEntryOptions GetDefaultCacheEntryOptions()
{
foreach (var configure in _cacheOption.CacheConfigurators)
{
var options = configure.Invoke(CacheName);
if (options != null)
{
return options;
}
}
return _cacheOption.GlobalCacheEntryOptions;
}
protected virtual void SetDefaultOptions()
{
CacheName = CacheNameAttribute.GetCacheName(typeof(TCacheItem));
//IgnoreMultiTenancy
IgnoreMultiTenancy = typeof(TCacheItem).IsDefined(typeof(IgnoreMultiTenancyAttribute), true);
//Configure default cache entry options
DefaultCacheOptions = GetDefaultCacheEntryOptions();
}
}
} }

@ -10,7 +10,18 @@ namespace Volo.Abp.Caching
/// Represents a distributed cache of <typeparamref name="TCacheItem" /> type. /// Represents a distributed cache of <typeparamref name="TCacheItem" /> type.
/// </summary> /// </summary>
/// <typeparam name="TCacheItem">The type of cache item being cached.</typeparam> /// <typeparam name="TCacheItem">The type of cache item being cached.</typeparam>
public interface IDistributedCache<TCacheItem> public interface IDistributedCache<TCacheItem> : IDistributedCache<TCacheItem, string>
where TCacheItem : class
{
}
/// <summary>
/// Represents a distributed cache of <typeparamref name="TCacheItem" /> type.
/// Uses a generic cache key type of <typeparamref name="TCacheKey" /> type.
/// </summary>
/// <typeparam name="TCacheItem">The type of cache item being cached.</typeparam>
/// <typeparam name="TCacheKey">The type of cache key being used.</typeparam>
public interface IDistributedCache<TCacheItem, TCacheKey>
where TCacheItem : class where TCacheItem : class
{ {
/// <summary> /// <summary>
@ -20,7 +31,7 @@ namespace Volo.Abp.Caching
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
/// <returns>The cache item, or null.</returns> /// <returns>The cache item, or null.</returns>
TCacheItem Get( TCacheItem Get(
string key, TCacheKey key,
bool? hideErrors = null bool? hideErrors = null
); );
@ -32,7 +43,7 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The cache item, or null.</returns> /// <returns>The cache item, or null.</returns>
Task<TCacheItem> GetAsync( Task<TCacheItem> GetAsync(
[NotNull] string key, [NotNull] TCacheKey key,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default CancellationToken token = default
); );
@ -47,7 +58,7 @@ namespace Volo.Abp.Caching
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
/// <returns>The cache item.</returns> /// <returns>The cache item.</returns>
TCacheItem GetOrAdd( TCacheItem GetOrAdd(
string key, TCacheKey key,
Func<TCacheItem> factory, Func<TCacheItem> factory,
Func<DistributedCacheEntryOptions> optionsFactory = null, Func<DistributedCacheEntryOptions> optionsFactory = null,
bool? hideErrors = null bool? hideErrors = null
@ -64,7 +75,7 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The cache item.</returns> /// <returns>The cache item.</returns>
Task<TCacheItem> GetOrAddAsync( Task<TCacheItem> GetOrAddAsync(
[NotNull] string key, [NotNull] TCacheKey key,
Func<Task<TCacheItem>> factory, Func<Task<TCacheItem>> factory,
Func<DistributedCacheEntryOptions> optionsFactory = null, Func<DistributedCacheEntryOptions> optionsFactory = null,
bool? hideErrors = null, bool? hideErrors = null,
@ -79,7 +90,7 @@ namespace Volo.Abp.Caching
/// <param name="options">The cache options for the value.</param> /// <param name="options">The cache options for the value.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
void Set( void Set(
string key, TCacheKey key,
TCacheItem value, TCacheItem value,
DistributedCacheEntryOptions options = null, DistributedCacheEntryOptions options = null,
bool? hideErrors = null bool? hideErrors = null
@ -95,7 +106,7 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns> /// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
Task SetAsync( Task SetAsync(
[NotNull] string key, [NotNull] TCacheKey key,
[NotNull] TCacheItem value, [NotNull] TCacheItem value,
[CanBeNull] DistributedCacheEntryOptions options = null, [CanBeNull] DistributedCacheEntryOptions options = null,
bool? hideErrors = null, bool? hideErrors = null,
@ -108,7 +119,7 @@ namespace Volo.Abp.Caching
/// <param name="key">The key of cached item to be retrieved from the cache.</param> /// <param name="key">The key of cached item to be retrieved from the cache.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
void Refresh( void Refresh(
string key, TCacheKey key,
bool? hideErrors = null bool? hideErrors = null
); );
@ -120,7 +131,7 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns> /// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
Task RefreshAsync( Task RefreshAsync(
string key, TCacheKey key,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default CancellationToken token = default
); );
@ -131,7 +142,7 @@ namespace Volo.Abp.Caching
/// <param name="key">The key of cached item to be retrieved from the cache.</param> /// <param name="key">The key of cached item to be retrieved from the cache.</param>
/// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param>
void Remove( void Remove(
string key, TCacheKey key,
bool? hideErrors = null bool? hideErrors = null
); );
@ -143,7 +154,7 @@ namespace Volo.Abp.Caching
/// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param>
/// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns> /// <returns>The <see cref="T:System.Threading.Tasks.Task" /> indicating that the operation is asynchronous.</returns>
Task RemoveAsync( Task RemoveAsync(
string key, TCacheKey key,
bool? hideErrors = null, bool? hideErrors = null,
CancellationToken token = default CancellationToken token = default
); );

@ -122,5 +122,192 @@ namespace Volo.Abp.Caching
cacheItem1.ShouldNotBeNull(); cacheItem1.ShouldNotBeNull();
} }
[Fact]
public async Task Should_Set_Get_And_Remove_Cache_Items_With_Integer_Type_CacheKey()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem, int>>();
var cacheKey = 42;
const string personName = "john nash";
//Get (not exists yet)
var cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
//Set
cacheItem = new PersonCacheItem(personName);
await personCache.SetAsync(cacheKey, cacheItem);
//Get (it should be available now
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldNotBeNull();
cacheItem.Name.ShouldBe(personName);
//Remove
await personCache.RemoveAsync(cacheKey);
//Get (not exists since removed)
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
}
[Fact]
public async Task GetOrAddAsync_With_Integer_Type_CacheKey()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem, int>>();
var cacheKey = 42;
const string personName = "john nash";
//Will execute the factory method to create the cache item
bool factoryExecuted = false;
var cacheItem = await personCache.GetOrAddAsync(cacheKey,
async () =>
{
factoryExecuted = true;
return new PersonCacheItem(personName);
});
factoryExecuted.ShouldBeTrue();
cacheItem.Name.ShouldBe(personName);
//This time, it will not execute the factory
factoryExecuted = false;
cacheItem = await personCache.GetOrAddAsync(cacheKey,
async () =>
{
factoryExecuted = true;
return new PersonCacheItem(personName);
});
factoryExecuted.ShouldBeFalse();
cacheItem.Name.ShouldBe(personName);
}
[Fact]
public async Task SameClassName_But_DiffNamespace_Should_Not_Use_Same_Cache_With_Integer_CacheKey()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem, int>>();
var otherPersonCache = GetRequiredService<IDistributedCache<Sail.Testing.Caching.PersonCacheItem, int>>();
var cacheKey = 42;
const string personName = "john nash";
//Get (not exists yet)
var cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
var cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldBeNull();
//Set
cacheItem = new PersonCacheItem(personName);
await personCache.SetAsync(cacheKey, cacheItem);
//Get (it should be available now, but otherPersonCache not exists now.
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldNotBeNull();
cacheItem.Name.ShouldBe(personName);
cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldBeNull();
//set other person cache
cacheItem1 = new Sail.Testing.Caching.PersonCacheItem(personName);
await otherPersonCache.SetAsync(cacheKey, cacheItem1);
cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldNotBeNull();
cacheItem1.Name.ShouldBe(personName);
//Remove
await personCache.RemoveAsync(cacheKey);
//Get (not exists since removed)
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
cacheItem1 = await otherPersonCache.GetAsync(cacheKey);
cacheItem1.ShouldNotBeNull();
}
[Fact]
public async Task Should_Set_Get_And_Remove_Cache_Items_With_Object_Type_CacheKey()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem, ComplexObjectAsCacheKey>>();
var cacheKey = new ComplexObjectAsCacheKey { Name = "DummyData", Age = 42 };
const string personName = "john nash";
//Get (not exists yet)
var cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
//Set
cacheItem = new PersonCacheItem(personName);
await personCache.SetAsync(cacheKey, cacheItem);
//Get (it should be available now
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldNotBeNull();
cacheItem.Name.ShouldBe(personName);
//Remove
await personCache.RemoveAsync(cacheKey);
//Get (not exists since removed)
cacheItem = await personCache.GetAsync(cacheKey);
cacheItem.ShouldBeNull();
}
[Fact]
public async Task Should_Set_Get_And_Remove_Cache_Items_For_Same_Object_Type_With_Different_CacheKeys()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem, ComplexObjectAsCacheKey>>();
var cache1Key = new ComplexObjectAsCacheKey { Name = "John", Age = 42 };
var cache2Key = new ComplexObjectAsCacheKey { Name = "Jenny", Age = 24 };
const string personName = "john nash";
//Get (not exists yet)
var cacheItem1 = await personCache.GetAsync(cache1Key);
var cacheItem2 = await personCache.GetAsync(cache2Key);
cacheItem1.ShouldBeNull();
cacheItem2.ShouldBeNull();
//Set
cacheItem1 = new PersonCacheItem(personName);
cacheItem2 = new PersonCacheItem(personName);
await personCache.SetAsync(cache1Key, cacheItem1);
await personCache.SetAsync(cache2Key, cacheItem2);
//Get (it should be available now
cacheItem1 = await personCache.GetAsync(cache1Key);
cacheItem1.ShouldNotBeNull();
cacheItem1.Name.ShouldBe(personName);
cacheItem2 = await personCache.GetAsync(cache2Key);
cacheItem2.ShouldNotBeNull();
cacheItem2.Name.ShouldBe(personName);
//Remove
await personCache.RemoveAsync(cache1Key);
await personCache.RemoveAsync(cache2Key);
//Get (not exists since removed)
cacheItem1 = await personCache.GetAsync(cache1Key);
cacheItem1.ShouldBeNull();
cacheItem2 = await personCache.GetAsync(cache2Key);
cacheItem2.ShouldBeNull();
}
} }
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Linq;
namespace Volo.Abp.Caching namespace Volo.Abp.Caching
{ {
[Serializable] [Serializable]
@ -17,7 +18,33 @@ namespace Volo.Abp.Caching
Name = name; Name = name;
} }
} }
public class ComplexObjectAsCacheKey
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
// Return selective fields
//return $"{Name}_{Age}";
// Return all the fields concatenated
var sb = new System.Text.StringBuilder();
var properties = this.GetType().GetProperties()
.Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(this, null);
if (value != null)
{
sb.Append(value.ToString());
}
}
return sb.ToString();
}
}
} }
namespace Sail.Testing.Caching namespace Sail.Testing.Caching
{ {
[Serializable] [Serializable]

Loading…
Cancel
Save