Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions LazyCache.UnitTests/CachingServiceMemoryCacheProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private static CachingService BuildCache()

private class ComplexTestObject
{
public readonly IList<object> SomeItems = new List<object> {1, 2, 3, "testing123"};
public readonly IList<object> SomeItems = new List<object> { 1, 2, 3, "testing123" };
public string SomeMessage = "testing123";
}

Expand Down Expand Up @@ -528,7 +528,7 @@ public async Task
Thread.Sleep(500);

Assert.That(callbackValue, Is.AssignableTo<Task<int>>());
var callbackResultValue = await (Task<int>) callbackValue;
var callbackResultValue = await (Task<int>)callbackValue;
Assert.AreEqual(123, callbackResultValue);
}

Expand Down Expand Up @@ -873,7 +873,7 @@ MemoryCacheEntryOptions GetOptions()
.SetAbsoluteExpiration(refreshInterval, ExpirationMode.ImmediateEviction);
options.RegisterPostEvictionCallback((keyEvicted, value, reason, state) =>
{
if (reason == EvictionReason.Expired || reason == EvictionReason.TokenExpired)
if (reason == EvictionReason.Expired || reason == EvictionReason.TokenExpired)
sut.GetOrAdd(key, _ => GetStuff(), GetOptions());
});
return options;
Expand Down Expand Up @@ -946,7 +946,7 @@ ComplexTestObject GetStuff()
{
var key = $"stuff-{hits % uniqueCacheItems}";
var cached = await sut.GetOrAddAsync(key, () => GetStuffAsync(), DateTimeOffset.UtcNow.AddSeconds(1));
if(!cancel.IsCancellationRequested) Interlocked.Increment(ref hits);
if (!cancel.IsCancellationRequested) Interlocked.Increment(ref hits);
}
});
});
Expand Down Expand Up @@ -1108,5 +1108,22 @@ public void RemovedItemCannotBeRetrievedFromCache()
sut.Remove(TestKey);
Assert.Null(sut.Get<object>(TestKey));
}

[Test]
public void TryGetReturnsCachedValueAndTrue()
{
string val = "Test Value";
string key = "testkey";
sut.Add(key, val);

var contains = sut.TryGetValue<string>(key, out var value);

Assert.IsTrue(contains);
Assert.AreEqual(value, val);

var contains2 = sut.TryGetValue<string>("invalidkey", out var value2);

Assert.IsFalse(contains2);
}
}
}
15 changes: 11 additions & 4 deletions LazyCache/CachingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public CachingService(ICacheProvider cache) : this(() => cache)
}

public static Lazy<ICacheProvider> DefaultCacheProvider { get; set; }
= new Lazy<ICacheProvider>(() =>
= new Lazy<ICacheProvider>(() =>
new MemoryCacheProvider(
new MemoryCache(
new MemoryCacheOptions())
Expand Down Expand Up @@ -89,6 +89,13 @@ public virtual Task<T> GetAsync<T>(string key)
return GetValueFromAsyncLazy<T>(item, out _);
}

public virtual bool TryGetValue<T>(string key, out object value)
{
ValidateKey(key);

return CacheProvider.TryGetValue(key, out value);
}

public virtual T GetOrAdd<T>(string key, Func<ICacheEntry, T> addItemFactory)
{
return GetOrAdd(key, addItemFactory, null);
Expand All @@ -112,7 +119,7 @@ object CacheFactory(ICacheEntry entry) =>
// acquire lock per key
uint hash = (uint)key.GetHashCode() % (uint)keyLocks.Length;
while (Interlocked.CompareExchange(ref keyLocks[hash], 1, 0) == 1) { Thread.Yield(); }

try
{
cacheItem = CacheProvider.GetOrCreate<object>(key, policy, CacheFactory);
Expand Down Expand Up @@ -179,7 +186,7 @@ public virtual Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> a

public virtual async Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> addItemFactory,
MemoryCacheEntryOptions policy)
{
{
ValidateKey(key);

object cacheItem;
Expand Down Expand Up @@ -280,7 +287,7 @@ protected virtual T GetValueFromLazy<T>(object item, out bool valueHasChangedTyp

protected virtual Task<T> GetValueFromAsyncLazy<T>(object item, out bool valueHasChangedType)
{
valueHasChangedType = false;
valueHasChangedType = false;
switch (item)
{
case AsyncLazy<T> asyncLazy:
Expand Down
2 changes: 2 additions & 0 deletions LazyCache/IAppCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public interface IAppCache
void Add<T>(string key, T item, MemoryCacheEntryOptions policy);
T Get<T>(string key);
Task<T> GetAsync<T>(string key);
bool TryGetValue<T>(string key, out object value);

T GetOrAdd<T>(string key, Func<ICacheEntry, T> addItemFactory);
T GetOrAdd<T>(string key, Func<ICacheEntry, T> addItemFactory, MemoryCacheEntryOptions policy);
Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> addItemFactory);
Expand Down
1 change: 1 addition & 0 deletions LazyCache/ICacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public interface ICacheProvider : IDisposable
object GetOrCreate<T>(string key, MemoryCacheEntryOptions policy, Func<ICacheEntry, T> func);
void Remove(string key);
Task<T> GetOrCreateAsync<T>(string key, Func<ICacheEntry, Task<T>> func);
bool TryGetValue(object key, out object value);
}
}
6 changes: 6 additions & 0 deletions LazyCache/Mocks/MockCacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace LazyCache.Mocks
{

public class MockCacheProvider : ICacheProvider
{
public void Set(string key, object item, MemoryCacheEntryOptions policy)
Expand Down Expand Up @@ -34,6 +35,11 @@ public Task<T> GetOrCreateAsync<T>(string key, Func<ICacheEntry, Task<T>> func)
return func(null);
}

public bool TryGetValue(object key, out object value)
{
throw new NotImplementedException();
}

public void Dispose()
{
}
Expand Down
6 changes: 6 additions & 0 deletions LazyCache/Mocks/MockCachingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,11 @@ public Task<T> GetAsync<T>(string key)
public void Add<T>(string key, T item, MemoryCacheEntryOptions policy)
{
}

public bool TryGetValue<T>(string key, out object value)
{
value = default(T);
return true;
}
}
}
10 changes: 8 additions & 2 deletions LazyCache/Providers/MemoryCacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public object GetOrCreate<T>(string key, Func<ICacheEntry, T> factory)

public object GetOrCreate<T>(string key, MemoryCacheEntryOptions policy, Func<ICacheEntry, T> factory)
{
if(policy == null)
if (policy == null)
return cache.GetOrCreate(key, factory);

if (!cache.TryGetValue(key, out var result))
Expand All @@ -47,7 +47,7 @@ public object GetOrCreate<T>(string key, MemoryCacheEntryOptions policy, Func<IC
var expiryTokenSource = new CancellationTokenSource();
var expireToken = new CancellationChangeToken(expiryTokenSource.Token);
entry.AddExpirationToken(expireToken);
entry.RegisterPostEvictionCallback((keyPost, value, reason, state) =>
entry.RegisterPostEvictionCallback((keyPost, value, reason, state) =>
expiryTokenSource.Dispose());

result = factory(entry);
Expand Down Expand Up @@ -78,6 +78,12 @@ public Task<T> GetOrCreateAsync<T>(string key, Func<ICacheEntry, Task<T>> factor
return cache.GetOrCreateAsync(key, factory);
}

public bool TryGetValue(object key, out object value)
{
return cache.TryGetValue(key, out value);
}


public void Dispose()
{
cache?.Dispose();
Expand Down