/// <summary> /// Initialise the in-memory cache using the delegates and caching period provided /// </summary> /// <param name="clonerFactory">An instance of the cloner factory to be used in cloning cache items</param> /// <param name="asyncRetrievalDelegate">The async delegate to await for retrieval of the object, e.g. from a database</param> /// <param name="syncRetrievalDelegate">The syncnronous delegate for retrieval of the object, e.g. from a database</param> /// <param name="cachingPeriod">The period for which caching is to be performed</param> /// <param name="initialRetrievalTimeout">The number of milliseconds to wait before timing out the first retrieval before returning the default</param> /// <param name="repeatRetrievalTimeout">The number of milliseconds to wait before timing out on repeat retrievals before returning stale data</param> /// <remarks>Either async or sync delegate may be null, but not both</remarks> public InMemoryItemCache(IDeepClonerFactory <T> clonerFactory, Func <Task <T> > asyncRetrievalDelegate, Func <T> syncRetrievalDelegate, TimeSpan cachingPeriod, int initialRetrievalTimeout = int.MaxValue, int repeatRetrievalTimeout = 100) { if (asyncRetrievalDelegate is null && syncRetrievalDelegate is null) { throw new ArgumentException("Either a synchronous or asynchronous delegate must be provided as a minimum!", "Delegates"); } _asyncRetrievalDelegate = asyncRetrievalDelegate; _syncRetrievalDelegate = syncRetrievalDelegate; _cachingPeriod = cachingPeriod; _repeatRetrievalTimeout = repeatRetrievalTimeout; // Create an instance of the default object cloner, for use when returning objects _clonerFactory = clonerFactory; // Create a default cache entry so that no null reference exceptions are encountered on first use // This item is marked as immediately expiring, so that it always triggers a request to the source _cacheEntry = new CacheEntry <T>(default(T), DateTime.MinValue, initialRetrievalTimeout); }
/// <summary> /// Create a new instance for use in caching some data /// </summary> /// <param name="logger">A logger to use for reporting issues with loading</param> /// <param name="clonerFactory">The factory for the cloner to in cloning the cached item prior to return</param> /// <param name="asyncLoadDelegate">The delegate that is used to load data</param> /// <param name="initialValue">The initial value to place into the cache, before loading is complete</param> /// <param name="refreshPeriod">The period between cache refreshes - the maxmimum data staleness</param> /// <param name="loadTimeout">The timeout for the load operation - defaults to Timeout.InfiniteTimeSpan</param> /// <exception cref="ArgumentException">One of the parameters was invalid</exception> public AutoRefreshingItemCache(ILogger logger, IDeepClonerFactory <T> clonerFactory, Func <CancellationToken, Task <T> > asyncLoadDelegate, T initialValue, TimeSpan refreshPeriod, TimeSpan?loadTimeout = null) { if (loadTimeout.HasValue && loadTimeout.Value.TotalMilliseconds < 0) { throw new ArgumentException(nameof(loadTimeout)); } if (refreshPeriod.TotalMilliseconds < 10) { throw new ArgumentException(nameof(refreshPeriod)); } _logger = logger; _clonerFactory = clonerFactory; _asyncLoadDelegate = asyncLoadDelegate; if (loadTimeout is null) { loadTimeout = Timeout.InfiniteTimeSpan; } _loadTimeout = loadTimeout.Value; _refreshPeriod = refreshPeriod; _cacheItem = new CacheItem <T>(initialValue); }