Skip to content

Commit

Permalink
Proper handling of null values on GetOrSet methods
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaabreu committed Oct 15, 2020
1 parent 5ea7569 commit c099c74
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 87 deletions.
6 changes: 6 additions & 0 deletions samples/Sample.Application/WeatherService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ public class WeatherService : IWeatherService

public async Task<WeatherForecast> FetchForecastAsync(DateTime date, CancellationToken cancellationToken)
{
// Value factories that return null don't get cached by GetOrSet extensions.
if (RNG.NextDouble() > 0.5)
{
return null;
}

// Simulate access to a database or third party service.
await Task.Delay(100, cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ public static Task SetAsync(this IDistributedCache cache, string key, byte[] val
}


public static byte[] GetOrSet(this IDistributedCache cache, string key, Func<byte[]> valueFactory)
public static byte[]? GetOrSet(this IDistributedCache cache, string key, Func<byte[]?> valueFactory)
{
return cache.GetOrSet(key, valueFactory, new DistributedCacheEntryOptions());
}

public static byte[] GetOrSet(this IDistributedCache cache, string key, Func<byte[]> valueFactory,
public static byte[]? GetOrSet(this IDistributedCache cache, string key, Func<byte[]?> valueFactory,
TimeSpan absoluteExpirationRelativeToNow)
{
return cache.GetOrSet(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow });
}

public static byte[] GetOrSet(this IDistributedCache cache, string key, Func<byte[]> valueFactory,
public static byte[]? GetOrSet(this IDistributedCache cache, string key, Func<byte[]?> valueFactory,
DistributedCacheEntryOptions options)
{
var cached = cache.Get(key);
Expand All @@ -44,26 +44,29 @@ public static byte[] GetOrSet(this IDistributedCache cache, string key, Func<byt

var value = valueFactory();

cache.Set(key, value, options);
if (value != null)
{
cache.Set(key, value, options);
}

return value;
}


public static Task<byte[]> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<byte[]>> valueFactory,
public static Task<byte[]?> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<byte[]?>> valueFactory,
CancellationToken token = default)
{
return cache.GetOrSetAsync(key, valueFactory, new DistributedCacheEntryOptions(), token);
}

public static Task<byte[]> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<byte[]>> valueFactory,
public static Task<byte[]?> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<byte[]?>> valueFactory,
TimeSpan absoluteExpirationRelativeToNow, CancellationToken token = default)
{
return cache.GetOrSetAsync(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow }, token);
}

public static async Task<byte[]> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<byte[]>> valueFactory,
public static async Task<byte[]?> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<byte[]?>> valueFactory,
DistributedCacheEntryOptions options, CancellationToken token = default)
{
var cached = await cache.GetAsync(key, token);
Expand All @@ -75,25 +78,28 @@ public static async Task<byte[]> GetOrSetAsync(this IDistributedCache cache, str

var value = await valueFactory();

await cache.SetAsync(key, value, options, token);
if (value != null)
{
await cache.SetAsync(key, value, options, token);
}

return value;
}


public static string GetOrSetString(this IDistributedCache cache, string key, Func<string> valueFactory)
public static string? GetOrSetString(this IDistributedCache cache, string key, Func<string?> valueFactory)
{
return cache.GetOrSetString(key, valueFactory, new DistributedCacheEntryOptions());
}

public static string GetOrSetString(this IDistributedCache cache, string key, Func<string> valueFactory,
public static string? GetOrSetString(this IDistributedCache cache, string key, Func<string?> valueFactory,
TimeSpan absoluteExpirationRelativeToNow)
{
return cache.GetOrSetString(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow });
}

public static string GetOrSetString(this IDistributedCache cache, string key, Func<string> valueFactory,
public static string? GetOrSetString(this IDistributedCache cache, string key, Func<string?> valueFactory,
DistributedCacheEntryOptions options)
{
var cached = cache.GetString(key);
Expand All @@ -105,27 +111,30 @@ public static string GetOrSetString(this IDistributedCache cache, string key, Fu

var value = valueFactory();

cache.SetString(key, value, options);
if (value != null)
{
cache.SetString(key, value, options);
}

return value;
}


public static Task<string> GetOrSetStringAsync(this IDistributedCache cache, string key,
Func<Task<string>> valueFactory, CancellationToken token = default)
public static Task<string?> GetOrSetStringAsync(this IDistributedCache cache, string key,
Func<Task<string?>> valueFactory, CancellationToken token = default)
{
return cache.GetOrSetStringAsync(key, valueFactory, new DistributedCacheEntryOptions(), token);
}

public static Task<string> GetOrSetStringAsync(this IDistributedCache cache, string key,
Func<Task<string>> valueFactory, TimeSpan absoluteExpirationRelativeToNow, CancellationToken token = default)
public static Task<string?> GetOrSetStringAsync(this IDistributedCache cache, string key,
Func<Task<string?>> valueFactory, TimeSpan absoluteExpirationRelativeToNow, CancellationToken token = default)
{
return cache.GetOrSetStringAsync(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow }, token);
}

public static async Task<string> GetOrSetStringAsync(this IDistributedCache cache, string key,
Func<Task<string>> valueFactory, DistributedCacheEntryOptions options, CancellationToken token = default)
public static async Task<string?> GetOrSetStringAsync(this IDistributedCache cache, string key,
Func<Task<string?>> valueFactory, DistributedCacheEntryOptions options, CancellationToken token = default)
{
var cached = await cache.GetStringAsync(key, token);

Expand All @@ -136,7 +145,10 @@ public static async Task<string> GetOrSetStringAsync(this IDistributedCache cach

var value = await valueFactory();

await cache.SetStringAsync(key, value, options, token);
if (value != null)
{
await cache.SetStringAsync(key, value, options, token);
}

return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,50 +35,50 @@ public static class DistributedCacheJsonExtensions



public static void SetJsonObject<T>(this IDistributedCache cache, string key, T? value,
public static void SetJsonObject<T>(this IDistributedCache cache, string key, T value,
JsonSerializerOptions? serializerOptions = null) where T : class
{
cache.SetJsonObject(key, value, new DistributedCacheEntryOptions(), serializerOptions);
}

public static void SetJsonObject<T>(this IDistributedCache cache, string key, T? value,
public static void SetJsonObject<T>(this IDistributedCache cache, string key, T value,
TimeSpan absoluteExpirationRelativeToNow, JsonSerializerOptions? serializerOptions = null) where T : class
{
cache.SetJsonObject(key, value,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow },
serializerOptions);
}

public static void SetJsonObject<T>(this IDistributedCache cache, string key, T? value,
public static void SetJsonObject<T>(this IDistributedCache cache, string key, T value,
DistributedCacheEntryOptions entryOptions, JsonSerializerOptions? serializerOptions = null) where T : class
{
var bytes = value != null ? JsonSerializer.SerializeToUtf8Bytes(value, serializerOptions) : null;
var bytes = JsonSerializer.SerializeToUtf8Bytes(value, serializerOptions);

cache.Set(key, bytes, entryOptions);
}


public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T? value,
public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T value,
CancellationToken token = default) where T : class
{
return cache.SetJsonObjectAsync(key, value, new DistributedCacheEntryOptions(), null, token);
}

public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T? value,
public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T value,
JsonSerializerOptions? serializerOptions, CancellationToken token = default) where T : class
{
return cache.SetJsonObjectAsync(key, value, new DistributedCacheEntryOptions(), serializerOptions, token);
}

public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T? value,
public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T value,
TimeSpan absoluteExpirationRelativeToNow, CancellationToken token = default) where T : class
{
return cache.SetJsonObjectAsync(key, value,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow },
null, token);
}

public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T? value,
public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T value,
TimeSpan absoluteExpirationRelativeToNow, JsonSerializerOptions? serializerOptions,
CancellationToken token = default) where T : class
{
Expand All @@ -87,33 +87,33 @@ public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string ke
serializerOptions, token);
}

public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T? value,
public static Task SetJsonObjectAsync<T>(this IDistributedCache cache, string key, T value,
DistributedCacheEntryOptions entryOptions, JsonSerializerOptions? serializerOptions = null,
CancellationToken token = default) where T : class
{
var bytes = value != null ? JsonSerializer.SerializeToUtf8Bytes(value, serializerOptions) : null;
var bytes = JsonSerializer.SerializeToUtf8Bytes(value, serializerOptions);

return cache.SetAsync(key, bytes, entryOptions, token);
}



public static T GetOrSetJsonObject<T>(this IDistributedCache cache, string key, Func<T> valueFactory,
public static T? GetOrSetJsonObject<T>(this IDistributedCache cache, string key, Func<T?> valueFactory,
JsonSerializerOptions? serializerOptions = null) where T : class
{
return cache.GetOrSetJsonObject(key, valueFactory, new DistributedCacheEntryOptions(), serializerOptions);
}


public static T GetOrSetJsonObject<T>(this IDistributedCache cache, string key, Func<T> valueFactory,
public static T? GetOrSetJsonObject<T>(this IDistributedCache cache, string key, Func<T?> valueFactory,
TimeSpan absoluteExpirationRelativeToNow, JsonSerializerOptions? serializerOptions = null) where T : class
{
return cache.GetOrSetJsonObject<T>(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow },
serializerOptions);
}

public static T GetOrSetJsonObject<T>(this IDistributedCache cache, string key, Func<T> valueFactory,
public static T? GetOrSetJsonObject<T>(this IDistributedCache cache, string key, Func<T?> valueFactory,
DistributedCacheEntryOptions entryOptions, JsonSerializerOptions? serializerOptions = null) where T : class
{
var cached = cache.GetJsonObject<T>(key, serializerOptions);
Expand All @@ -125,50 +125,53 @@ public static T GetOrSetJsonObject<T>(this IDistributedCache cache, string key,

var value = valueFactory();

cache.SetJsonObject(key, value, entryOptions, serializerOptions);
if (value != null)
{
cache.SetJsonObject(key, value, entryOptions, serializerOptions);
}

return value;
}


public static Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T>> valueFactory, CancellationToken token = default) where T : class
public static Task<T?> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T?>> valueFactory, CancellationToken token = default) where T : class
{
return cache.GetOrSetJsonObjectAsync(key, valueFactory, new DistributedCacheEntryOptions(), null, token);
}
public static Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T>> valueFactory, JsonSerializerOptions? serializerOptions,
public static Task<T?> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T?>> valueFactory, JsonSerializerOptions? serializerOptions,
CancellationToken token = default) where T : class
{
return cache.GetOrSetJsonObjectAsync(key, valueFactory, new DistributedCacheEntryOptions(), serializerOptions, token);
}

public static Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T>> valueFactory, TimeSpan absoluteExpirationRelativeToNow, JsonSerializerOptions? serializerOptions,
public static Task<T?> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T?>> valueFactory, TimeSpan absoluteExpirationRelativeToNow, JsonSerializerOptions? serializerOptions,
CancellationToken token = default) where T : class
{
return cache.GetOrSetJsonObjectAsync(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow },
serializerOptions, token);
}

public static Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T>> valueFactory, TimeSpan absoluteExpirationRelativeToNow, CancellationToken token = default) where T : class
public static Task<T?> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T?>> valueFactory, TimeSpan absoluteExpirationRelativeToNow, CancellationToken token = default) where T : class
{
return cache.GetOrSetJsonObjectAsync(key, valueFactory,
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow },
null, token);
}

public static Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T>> valueFactory, DistributedCacheEntryOptions entryOptions,
public static Task<T?> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T?>> valueFactory, DistributedCacheEntryOptions entryOptions,
CancellationToken token = default) where T : class
{
return cache.GetOrSetJsonObjectAsync<T>(key, valueFactory, entryOptions, null, token);
}

public static async Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T>> valueFactory, DistributedCacheEntryOptions entryOptions,
public static async Task<T?> GetOrSetJsonObjectAsync<T>(this IDistributedCache cache, string key,
Func<Task<T?>> valueFactory, DistributedCacheEntryOptions entryOptions,
JsonSerializerOptions? serializerOptions = null, CancellationToken token = default) where T : class
{
var cached = await cache.GetJsonObjectAsync<T>(key, serializerOptions, token);
Expand All @@ -180,7 +183,10 @@ public static async Task<T> GetOrSetJsonObjectAsync<T>(this IDistributedCache ca

var value = await valueFactory();

await cache.SetJsonObjectAsync(key, value, entryOptions, serializerOptions, token);
if (value != null)
{
await cache.SetJsonObjectAsync(key, value, entryOptions, serializerOptions, token);
}

return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace SimpleConcepts.Extensions.Caching
{
public interface IValueSerializer
{
byte[]? Serialize(object? value);
byte[] Serialize(object value);
object? Deserialize(byte[]? bytes, Type type);
}
}
Loading

0 comments on commit c099c74

Please sign in to comment.