using System; using System.Threading.Tasks; namespace Config.Net.Core { /// /// Implements a lazy value i.e. that can expire in future /// /// class LazyVar where T : class { private readonly Func>? _renewFuncAsync; private readonly Func? _renewFunc; private DateTime _lastRenewed = DateTime.MinValue; private readonly TimeSpan _timeToLive; private T? _value; /// /// Creates an instance of a lazy variable with time-to-live value /// /// Time to live. Setting to disables caching completely /// public LazyVar(TimeSpan timeToLive, Func> renewFunc) { _timeToLive = timeToLive; _renewFuncAsync = renewFunc ?? throw new ArgumentNullException(nameof(renewFunc)); _renewFunc = null; } /// /// Creates an instance of a lazy variable with time-to-live value /// /// Time to live. Setting to disables caching completely /// public LazyVar(TimeSpan timeToLive, Func renewFunc) { _timeToLive = timeToLive; _renewFuncAsync = null; _renewFunc = renewFunc ?? throw new ArgumentNullException(nameof(renewFunc)); } /// /// Gets the values, renewing it if necessary /// /// Value public async Task GetValueAsync() { if (_renewFuncAsync == null) { throw new InvalidOperationException("cannot renew value, async delegate is not specified"); } if (_timeToLive == TimeSpan.Zero) { return await _renewFuncAsync(); } bool expired = (DateTime.UtcNow - _lastRenewed) > _timeToLive; if (expired) { _value = await _renewFuncAsync(); _lastRenewed = DateTime.UtcNow; } return _value; } /// /// Gets the values, renewing it if necessary /// /// Value public T? GetValue() { if (_renewFunc == null) { throw new InvalidOperationException("cannot renew value, synchronous delegate is not specified"); } if (_timeToLive == TimeSpan.Zero) { return _renewFunc(); } bool expired = (DateTime.UtcNow - _lastRenewed) > _timeToLive; if (expired) { _value = _renewFunc(); _lastRenewed = DateTime.UtcNow; } return _value; } } }