CodeByDay.Cache 1.2.0

Adds an Object which caches. Provide it a key and a function to populate the value.

Install-Package CodeByDay.Cache -Version 1.2.0
dotnet add package CodeByDay.Cache --version 1.2.0
<PackageReference Include="CodeByDay.Cache" Version="1.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CodeByDay.Cache --version 1.2.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Cache By Day

Repo for the Cache By Day NuGet package: https://www.nuget.org/packages/CodeByDay.Cache

Adds an Object which will act as a cache. Provide it a key and a function to populate the value.

Release Notes

1.2.0 [2019 Apr 23]:

  • Added WeakDictionaryStorage which can be used to make any kind of cache store its items as weak references.

  • Obsoleted WeakCache. Use 'new Cache<TKey, TValue>(new WeakDictionaryStorage<TKey, BaseCachedItem<TValue>>())' instead.

  • All code changes can be found here: https://bitbucket.org/Travis_Daily/codebyday.cache/branches/compare/1.2.0%0D1.1.1?w=1#diff

1.1.1 [2018 Oct 21]: TimedCache and TimedItemedCache will now always mark expired items as 'invalid'. Previously, if IsValid was true during serialization, and the Item expired before being deserialized, IsValid would stay 'true'. Now it will properly become 'false'.

Usage Guide

Cache Kinds

Kinds of Caches available natively:

  1. Cache: Stores all items.

  2. TimedCache: Stores all items for a given TimeSpan. A TimeSpan can also be specified when Getting/Setting a cached item.

  3. ItemedCache: Stores items up to the given limit.

  4. TimedItemedCache: Stores items up to the given limit for a given TimeSpan.

Additionally, you can pass a WeakDictionaryStorage object into the constructor of any of these caches. This will allow storage weak references which will be removed as needed by the Garbage Collector.

Creating a Cache

A cache is created like any other object:

#!c#
ICache<string, int> cache = new Cache<string, int>();

Using a Cache

Putting items into the cache and getting items out of the cache is handled by the ICache<K, V>.Get() function. This function takes the key as the first parameter, and a function which returns a value if the value cannot be found.

#!c#
var str = "Test String";
var length = cache.Get(str, () => str.Length);

In this example, since there is no existing value for our key "Test String", the function passed in will be executed, and the result of that function will be both stored in the cache and returned from the ICache<K, V>.Get() call. Any subsequent calls with a key value of "Test String" will not evaluate the function, and will instead return the cached value.

#!c#
var str = "Test String";
cache.Get(str, () => str.Length);
var length = cache.Get(str, () => -1);
// length == 11

This function is the also way to prime the cache. You can call ICache<K, V>.Get() and not read the result. This will store the value.

Also available is ICache<K, V>.TryGet(). This will return 'true' when a cached value is found and will populate the out param. If 'false' is returned, then the value of the out param is undefined.

#!c#
if (cache.TryGet(str, out int intOut))
{
  // Use value.
}
else
{
  // Error.
}

Clearing a Cache

ICache.Clear() will remove all keys from the cache. You can use this to force all your cache code to reevaluate the results. If you know only one item needs to be removed, you can call ICache<K>.Remove(Key). This function can take an IEnumerable of Keys or you can pass keys one by one as params:

#!c#
cache.Remove(key0);
cache.Remove(key1, key2, key3);
cache.Remove(new List<Key>{ key4, key5, key6 });

ICache.Clear() and ICache.Remove() block the thread that calls it.

The current implementation of the Cache in Cache By Day will run a task to clean the Cache during a call to Get() when the Cache knows that there are invalid values.

ExecuteCached

Func<>.ExecuteCached() is a set of extensions methods to Func<> that will execute the Func<> and store the result in a cache. These cached values are stored per Func<> object and params passed in, so calling ExecuteCached() with two functions which happen to do the same thing will still cause each of the functions to be executed.

#!c#
Func<string> f1 = () => {
  System.Console.WriteLine("f1");
  return "f1";
};

Func<string> f2 = () => {
  System.Console.WriteLine("f1");
  return "f1";
};

f1.ExecuteCached();
f1.ExecuteCached();
System.Console.WriteLine("---")
f2.ExecuteCached();
f2.ExecuteCached();

This will print:

#!c#
f1
---
f1

There are also overloads that take objects to pass into the function.

Note that using these extensions means your Func<> objects and their results will be kept in memory: this is a memory leak! However, you can manually clear these object by calling FuncExtensions.Clear().

IStorage

Cached items are stored in an IStorage. By default a dictionary is used, but a custom object can be used instead. Using a custom object allows the control of the storage of the items, such as saving them into a database.

Supported .Net Versions

Naturally, anything newer than .Net Framework 3.5 or .Net Standard 1.1 is also supported.

Note that .Net Framework 3.5 and 4.0 are supported with custom-written shims. This is noteworthy as these shims could possibly not produce the same result as the native functions in a newer version of the framework. These shims will be supported just as much as all the other code in Cache By Day, so if you do find a discrepancy, please report it.

These shims are internal, so you should not need to worry about accidentally using them in your program.

.Net 3.5 Shims

  1. Task.Run() is simulated by creating a new thread with the given action to run. This causes quite a bit more overhead in comparison to .Net 4 and up. This is used in ICache<K, V>.Get() when a cache thinks it should be cleaned.
  2. Tuple creates KeyValuePair objects. This is used in FuncExtentions.

.Net 4.0 Shims

  1. Task.Run() does not exist in .Net 4.0, but Task.Run() is really just shorthand for System.Threading.Tasks.Task.Factory.StartNew(action, CancellationToken.None);. Thus, the shim simply adds Task.Run() as this line.

Repo

Branches

The branches in this repo relate directly to the release they are building up to. Once a release has been made, the branch is no longer commited to. This effectively means there is no "master" branch: only releases.

Versioning

This project uses Semantic Versioning 2.0.0

If you're making a NuGet package, I recommend editing your .csproj to force this Semantic Versioning. This example requires a version equal to or above 1.2.0 and disallows 2.0.0 or above.

<PackageReference Include="CodeByDay.Cache" Version="[1.2.0,2.0.0)" />

Have an Issue?

If you find any issues with this NuGet, please use the Contact owners link on the NuGet page.

Cache By Day

Repo for the Cache By Day NuGet package: https://www.nuget.org/packages/CodeByDay.Cache

Adds an Object which will act as a cache. Provide it a key and a function to populate the value.

Release Notes

1.2.0 [2019 Apr 23]:

  • Added WeakDictionaryStorage which can be used to make any kind of cache store its items as weak references.

  • Obsoleted WeakCache. Use 'new Cache<TKey, TValue>(new WeakDictionaryStorage<TKey, BaseCachedItem<TValue>>())' instead.

  • All code changes can be found here: https://bitbucket.org/Travis_Daily/codebyday.cache/branches/compare/1.2.0%0D1.1.1?w=1#diff

1.1.1 [2018 Oct 21]: TimedCache and TimedItemedCache will now always mark expired items as 'invalid'. Previously, if IsValid was true during serialization, and the Item expired before being deserialized, IsValid would stay 'true'. Now it will properly become 'false'.

Usage Guide

Cache Kinds

Kinds of Caches available natively:

  1. Cache: Stores all items.

  2. TimedCache: Stores all items for a given TimeSpan. A TimeSpan can also be specified when Getting/Setting a cached item.

  3. ItemedCache: Stores items up to the given limit.

  4. TimedItemedCache: Stores items up to the given limit for a given TimeSpan.

Additionally, you can pass a WeakDictionaryStorage object into the constructor of any of these caches. This will allow storage weak references which will be removed as needed by the Garbage Collector.

Creating a Cache

A cache is created like any other object:

#!c#
ICache<string, int> cache = new Cache<string, int>();

Using a Cache

Putting items into the cache and getting items out of the cache is handled by the ICache<K, V>.Get() function. This function takes the key as the first parameter, and a function which returns a value if the value cannot be found.

#!c#
var str = "Test String";
var length = cache.Get(str, () => str.Length);

In this example, since there is no existing value for our key "Test String", the function passed in will be executed, and the result of that function will be both stored in the cache and returned from the ICache<K, V>.Get() call. Any subsequent calls with a key value of "Test String" will not evaluate the function, and will instead return the cached value.

#!c#
var str = "Test String";
cache.Get(str, () => str.Length);
var length = cache.Get(str, () => -1);
// length == 11

This function is the also way to prime the cache. You can call ICache<K, V>.Get() and not read the result. This will store the value.

Also available is ICache<K, V>.TryGet(). This will return 'true' when a cached value is found and will populate the out param. If 'false' is returned, then the value of the out param is undefined.

#!c#
if (cache.TryGet(str, out int intOut))
{
  // Use value.
}
else
{
  // Error.
}

Clearing a Cache

ICache.Clear() will remove all keys from the cache. You can use this to force all your cache code to reevaluate the results. If you know only one item needs to be removed, you can call ICache<K>.Remove(Key). This function can take an IEnumerable of Keys or you can pass keys one by one as params:

#!c#
cache.Remove(key0);
cache.Remove(key1, key2, key3);
cache.Remove(new List<Key>{ key4, key5, key6 });

ICache.Clear() and ICache.Remove() block the thread that calls it.

The current implementation of the Cache in Cache By Day will run a task to clean the Cache during a call to Get() when the Cache knows that there are invalid values.

ExecuteCached

Func<>.ExecuteCached() is a set of extensions methods to Func<> that will execute the Func<> and store the result in a cache. These cached values are stored per Func<> object and params passed in, so calling ExecuteCached() with two functions which happen to do the same thing will still cause each of the functions to be executed.

#!c#
Func<string> f1 = () => {
  System.Console.WriteLine("f1");
  return "f1";
};

Func<string> f2 = () => {
  System.Console.WriteLine("f1");
  return "f1";
};

f1.ExecuteCached();
f1.ExecuteCached();
System.Console.WriteLine("---")
f2.ExecuteCached();
f2.ExecuteCached();

This will print:

#!c#
f1
---
f1

There are also overloads that take objects to pass into the function.

Note that using these extensions means your Func<> objects and their results will be kept in memory: this is a memory leak! However, you can manually clear these object by calling FuncExtensions.Clear().

IStorage

Cached items are stored in an IStorage. By default a dictionary is used, but a custom object can be used instead. Using a custom object allows the control of the storage of the items, such as saving them into a database.

Supported .Net Versions

Naturally, anything newer than .Net Framework 3.5 or .Net Standard 1.1 is also supported.

Note that .Net Framework 3.5 and 4.0 are supported with custom-written shims. This is noteworthy as these shims could possibly not produce the same result as the native functions in a newer version of the framework. These shims will be supported just as much as all the other code in Cache By Day, so if you do find a discrepancy, please report it.

These shims are internal, so you should not need to worry about accidentally using them in your program.

.Net 3.5 Shims

  1. Task.Run() is simulated by creating a new thread with the given action to run. This causes quite a bit more overhead in comparison to .Net 4 and up. This is used in ICache<K, V>.Get() when a cache thinks it should be cleaned.
  2. Tuple creates KeyValuePair objects. This is used in FuncExtentions.

.Net 4.0 Shims

  1. Task.Run() does not exist in .Net 4.0, but Task.Run() is really just shorthand for System.Threading.Tasks.Task.Factory.StartNew(action, CancellationToken.None);. Thus, the shim simply adds Task.Run() as this line.

Repo

Branches

The branches in this repo relate directly to the release they are building up to. Once a release has been made, the branch is no longer commited to. This effectively means there is no "master" branch: only releases.

Versioning

This project uses Semantic Versioning 2.0.0

If you're making a NuGet package, I recommend editing your .csproj to force this Semantic Versioning. This example requires a version equal to or above 1.2.0 and disallows 2.0.0 or above.

<PackageReference Include="CodeByDay.Cache" Version="[1.2.0,2.0.0)" />

Have an Issue?

If you find any issues with this NuGet, please use the Contact owners link on the NuGet page.

  • .NETFramework 3.5

    • No dependencies.
  • .NETFramework 4.0

    • No dependencies.
  • .NETFramework 4.5

    • No dependencies.
  • .NETStandard 1.1

Version History

Version Downloads Last updated
1.2.0 112 4/23/2019
1.1.1 144 10/21/2018
1.1.0 234 1/19/2018
1.0.1 211 1/14/2018
1.0.0 257 12/6/2017