Caching
Our caching provider is built on top of Microsoft.Extensions.Caching.Memory Caching is insanely easy with request handlers in Shiny Mediator.
-
Install Shiny.Mediator.Caching.MicrosoftMemoryCache
to your project.
-
Create your request handler - you can mark Cache here with the attribute or you can use Configuration.
[Cache]public class MyHandler : IRequestHandler<MyRequest, MyResult>{public async Task<MyResult> Handle(MyRequest request, RequestContext<MyRequest> context, CancellationToken ct){return new MyResult();}} -
In your host startup, with the AddShinyMediator call, add the following:
services.AddShinyMediator(x => x..AddMemoryCaching(y =>{y.ExpirationScanFrequency = TimeSpan.FromSeconds(5);}));
There are many additional properties you can use to interact with the cache setup
public class CacheAttribute : Attribute{ public int AbsoluteExpirationSeconds { get; set; } public int SlidingExpirationSeconds { get; set; }}
Deeper Cache Control
You can add the ICacheControl to your contract to control cache directly at the point of call.
ForceRefresh allows an easy way to bypass cache and SetEntry allows you to set cache entry properties.
public class MyContract : IRequest<SomeResponse>, ICacheControl{ public bool ForceRefresh { get; set; } public Action<ICacheEntry>? SetEntry { get; set; } // optional: allows you to set cache entry properties}
Configuration
We recommend configuring cache through Microsoft.Extensions.Configuration. Read Configuration for more information.
{ "Mediator": { "Cache": { "My.Namespace.MyHandler": { "Priority": "High", "AbsoluteExpirationSeconds": 60, "SlidingExpirationSeconds": 30 } } }}
Persistent Cache
Persistent cache is built into Shiny.Mediator.Maui and Shiny.Mediator.Prism. It uses the file system to store cache data. This allows cache to survive across application restarts. It works identical to the memory cache, but you can specify a different cache provider.
services.AddShinyMediator(x =>{ x.AddPersistentCache();});
Custom Cache providers
Custom caching is now easy to accomplish inside Shiny.Mediator. Your cache provider can also make use of all the same benefits/configuration as already shown.
-
Implement your custom provider
Shiny.Mediator.Caching.ICacheProvider
located in the Shiny.Mediator package.public interface ICacheService{Task<CacheEntry<T>?> GetOrCreate<T>(string key,Func<Task<T>> factory,CacheItemConfig? config = null);/// <summary>/// Manually insert or overwrite an item in cache/// </summary>/// <param name="key"></param>/// <param name="value"></param>/// <param name="config"></param>Task Set<T>(string key,T value,CacheItemConfig? config = null);/// <summary>/// Retrieves a cached value, null if not found/// </summary>/// <param name="key"></param>/// <typeparam name="T"></typeparam>/// <returns></returns>Task<CacheEntry<T>?> Get<T>(string key);/// <summary>/// Removes a specific cache item/// </summary>/// <param name="key"></param>Task Remove(string key);/// <summary>/// Clears cache keys starting with prefix/// </summary>/// <param name="prefix"></param>Task RemoveByPrefix(string prefix);/// <summary>/// Clears all cache/// </summary>Task Clear();}- Now register it with Shiny.Mediator
services.AddShinyMediator(x => x.AddCaching<MyCustomCacheService>());You can only have 1 cache provider registered at a time for our middleware. If you need something more custom, you’ll need to create your own middleware to handle it.
Contexts & ‘Did my data come from cache’?
TODO