Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue72 Deprecate Add<T> method in favor of Set<T> #136

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
131 changes: 131 additions & 0 deletions LazyCache.UnitTests/CachingServiceMemoryCacheProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,137 @@ public void AddWithSlidingThatExpiresReturnsNull()
Assert.IsNull(sut.Get<string>(TestKey));
}

[Test]
public void SetComplexObjectThenGetGenericReturnsCachedObject()
{
testObject.SomeItems.Add("Another");
testObject.SomeMessage = "changed-it-up";
sut.Set(TestKey, testObject);
var actual = sut.Get<ComplexTestObject>(TestKey);
var expected = testObject;
Assert.NotNull(actual);
Assert.AreEqual(expected, actual);
testObject.SomeItems.Should().Contain("Another");
testObject.SomeMessage.Should().Be("changed-it-up");
}

[Test]
public void SetComplexObjectThenGetReturnsCachedObject()
{
sut.Set(TestKey, testObject);
var actual = sut.Get<object>(TestKey) as ComplexTestObject;
var expected = testObject;
Assert.NotNull(actual);
Assert.AreEqual(expected, actual);
}

[Test]
public void SetEmptyKeyThrowsException()
{
Action act = () => sut.Set("", new object());
act.Should().Throw<ArgumentOutOfRangeException>();
}

[Test]
public void SetEmptyKeyThrowsExceptionWithExpiration()
{
Action act = () => sut.Set("", new object(), DateTimeOffset.Now.AddHours(1));
act.Should().Throw<ArgumentOutOfRangeException>();
}

[Test]
public void SetEmptyKeyThrowsExceptionWithPolicy()
{
Action act = () => sut.Set("", new object(), new MemoryCacheEntryOptions());
act.Should().Throw<ArgumentOutOfRangeException>();
}

[Test]
public void SetEmptyKeyThrowsExceptionWithSliding()
{
Action act = () => sut.Set("", new object(), new TimeSpan(1000));
act.Should().Throw<ArgumentOutOfRangeException>();
}

[Test]
public void SetNullKeyThrowsException()
{
Action act = () => sut.Set(null, new object());
act.Should().Throw<ArgumentNullException>();
}

[Test]
public void SetNullKeyThrowsExceptionWithExpiration()
{
Action act = () => sut.Set(null, new object(), DateTimeOffset.Now.AddHours(1));
act.Should().Throw<ArgumentNullException>();
}

[Test]
public void SetNullKeyThrowsExceptionWithPolicy()
{
Action act = () => sut.Set(null, new object(), new MemoryCacheEntryOptions());
act.Should().Throw<ArgumentNullException>();
}

[Test]
public void SetNullKeyThrowsExceptionWithSliding()
{
Action act = () => sut.Set(null, new object(), new TimeSpan(1000));
act.Should().Throw<ArgumentNullException>();
}

[Test]
public void SetNullThrowsException()
{
Action act = () => sut.Add<object>(TestKey, null);
act.Should().Throw<ArgumentNullException>();
}

[Test]
public void SetThenGetReturnsCachedObject()
{
sut.Set(TestKey, "testObject");
Assert.AreEqual("testObject", sut.Get<string>(TestKey));
}

[Test]
public void SetWithOffsetReturnsCachedItem()
{
sut.Set(TestKey, "testObject", DateTimeOffset.Now.AddSeconds(1));
Assert.AreEqual("testObject", sut.Get<string>(TestKey));
}

[Test]
public void SetWithOffsetThatExpiresReturnsNull()
{
sut.Set(TestKey, "testObject", DateTimeOffset.Now.AddSeconds(1));
Thread.Sleep(1500);
Assert.IsNull(sut.Get<string>(TestKey));
}

[Test]
public void SetWithPolicyReturnsCachedItem()
{
sut.Set(TestKey, "testObject", new MemoryCacheEntryOptions());
Assert.AreEqual("testObject", sut.Get<string>(TestKey));
}

[Test]
public void SetWithSlidingReturnsCachedItem()
{
sut.Set(TestKey, "testObject", new TimeSpan(5000));
Assert.AreEqual("testObject", sut.Get<string>(TestKey));
}

[Test]
public void SetWithSlidingThatExpiresReturnsNull()
{
sut.Set(TestKey, "testObject", new TimeSpan(750));
Thread.Sleep(1500);
Assert.IsNull(sut.Get<string>(TestKey));
}

[Test]
public void CacheProviderIsNotNull()
{
Expand Down
44 changes: 44 additions & 0 deletions LazyCache.UnitTests/DeprecationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace LazyCache.UnitTests
{
public class DeprecationTests
{
[Test]
public void AllImplementationsOfIAppCache_HaveTheAddMethod_MarkedAsObsolete()
{
var classesWithoutObsoleteTag = new List<Type>();

foreach (var type in GetTypesWithIAppCache())
{
if (MethodDoesNotHaveObsoleteAttribute(type))
{
classesWithoutObsoleteTag.Add(type);
}
}
CollectionAssert.IsEmpty(classesWithoutObsoleteTag);
}

private IEnumerable<Type> GetTypesWithIAppCache()
{
var iAppCache = typeof(IAppCache);
return Assembly.GetAssembly(iAppCache)
.GetTypes()
.Where(iAppCache.IsAssignableFrom);
}

private bool MethodDoesNotHaveObsoleteAttribute(Type type)
{
var method = type.GetMethods()
.SingleOrDefault(m => m.Name == nameof(IAppCache.Add));
var attribute = method?.GetCustomAttributes(typeof(ObsoleteAttribute), true)
.SingleOrDefault() as ObsoleteAttribute;
return attribute == null;
}

}
}
36 changes: 27 additions & 9 deletions LazyCache/AppCacheExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,22 @@ namespace LazyCache
{
public static class AppCacheExtensions
{
[Obsolete("This method has been deprecated. Use Set<T> instead.", false)]
public static void Add<T>(this IAppCache cache, string key, T item)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));

cache.Add(key, item, cache.DefaultCachePolicy.BuildOptions());
Set(cache, key, item);
}

[Obsolete("This method has been deprecated. Use Set<T> instead.", false)]
public static void Add<T>(this IAppCache cache, string key, T item, DateTimeOffset expires)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));

cache.Add(key, item, new MemoryCacheEntryOptions {AbsoluteExpiration = expires});
Set(cache, key, item, expires);
}

[Obsolete("This method has been deprecated. Use Set<T> instead.", false)]
public static void Add<T>(this IAppCache cache, string key, T item, TimeSpan slidingExpiration)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));

cache.Add(key, item, new MemoryCacheEntryOptions {SlidingExpiration = slidingExpiration});
Set(cache, key, item, slidingExpiration);
}

public static T GetOrAdd<T>(this IAppCache cache, string key, Func<T> addItemFactory)
Expand Down Expand Up @@ -116,5 +113,26 @@ public static Task<T> GetOrAddAsync<T>(this IAppCache cache, string key, Func<Ta

return cache.GetOrAddAsync(key, _=> addItemFactory(), policy);
}

public static void Set<T>(this IAppCache cache, string key, T item)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));

cache.Set(key, item, cache.DefaultCachePolicy.BuildOptions());
}

public static void Set<T>(this IAppCache cache, string key, T item, DateTimeOffset expires)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));

cache.Set(key, item, new MemoryCacheEntryOptions { AbsoluteExpiration = expires });
}

public static void Set<T>(this IAppCache cache, string key, T item, TimeSpan slidingExpiration)
{
if (cache == null) throw new ArgumentNullException(nameof(cache));

cache.Set(key, item, new MemoryCacheEntryOptions { SlidingExpiration = slidingExpiration });
}
}
}
34 changes: 20 additions & 14 deletions LazyCache/CachingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,10 @@ public virtual int DefaultCacheDuration
/// </summary>
public virtual CacheDefaults DefaultCachePolicy { get; set; } = new CacheDefaults();

[Obsolete("This method has been deprecated. Use Set<T> instead.", false)]
public virtual void Add<T>(string key, T item, MemoryCacheEntryOptions policy)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
ValidateKey(key);

CacheProvider.Set(key, item, policy);
Set(key, item, policy);
}

public virtual T Get<T>(string key)
Expand Down Expand Up @@ -155,15 +152,6 @@ object CacheFactory(ICacheEntry entry) =>
}
}

private static void SetAbsoluteExpirationFromRelative(ICacheEntry entry)
{
if (!entry.AbsoluteExpirationRelativeToNow.HasValue) return;

var absoluteExpiration = DateTimeOffset.UtcNow + entry.AbsoluteExpirationRelativeToNow.Value;
if (!entry.AbsoluteExpiration.HasValue || absoluteExpiration < entry.AbsoluteExpiration)
entry.AbsoluteExpiration = absoluteExpiration;
}

public virtual void Remove(string key)
{
ValidateKey(key);
Expand Down Expand Up @@ -247,6 +235,15 @@ object CacheFactory(ICacheEntry entry) =>
}
}

public virtual void Set<T>(string key, T item, MemoryCacheEntryOptions policy)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
ValidateKey(key);

CacheProvider.Set(key, item, policy);
}

protected virtual T GetValueFromLazy<T>(object item, out bool valueHasChangedType)
{
valueHasChangedType = false;
Expand Down Expand Up @@ -334,5 +331,14 @@ protected virtual void ValidateKey(string key)
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentOutOfRangeException(nameof(key), "Cache keys cannot be empty or whitespace");
}

private static void SetAbsoluteExpirationFromRelative(ICacheEntry entry)
{
if (!entry.AbsoluteExpirationRelativeToNow.HasValue) return;

var absoluteExpiration = DateTimeOffset.UtcNow + entry.AbsoluteExpirationRelativeToNow.Value;
if (!entry.AbsoluteExpiration.HasValue || absoluteExpiration < entry.AbsoluteExpiration)
entry.AbsoluteExpiration = absoluteExpiration;
}
}
}
2 changes: 2 additions & 0 deletions LazyCache/IAppCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public interface IAppCache
/// Define the number of seconds to cache objects for by default
/// </summary>
CacheDefaults DefaultCachePolicy { get; }
[Obsolete("This method has been deprecated. Use Set<T> instead.", false)]
void Add<T>(string key, T item, MemoryCacheEntryOptions policy);
T Get<T>(string key);
Task<T> GetAsync<T>(string key);
Expand All @@ -20,5 +21,6 @@ public interface IAppCache
Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> addItemFactory);
Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> addItemFactory, MemoryCacheEntryOptions policy);
void Remove(string key);
void Set<T>(string key, T item, MemoryCacheEntryOptions policy);
}
}
6 changes: 6 additions & 0 deletions LazyCache/Mocks/MockCachingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ public Task<T> GetAsync<T>(string key)
return Task.FromResult(default(T));
}

[Obsolete("This method has been deprecated. Use Set<T> instead.", false)]
public void Add<T>(string key, T item, MemoryCacheEntryOptions policy)
{
Set(key, item, policy);
}

public void Set<T>(string key, T item, MemoryCacheEntryOptions policy)
{
}
}
Expand Down