using System ;
using System.Collections.Concurrent ;
using System.Collections.Generic ;
using System.Linq ;
using NzbDrone.Common.EnsureThat ;
namespace NzbDrone.Common.Cache
{
public class Cached < T > : ICached < T >
{
private class CacheItem
{
public T Object { get ; private set ; }
public DateTime ? ExpiryTime { get ; private set ; }
public CacheItem ( T obj , TimeSpan ? lifetime = null )
{
Object = obj ;
if ( lifetime . HasValue )
{
ExpiryTime = DateTime . UtcNow + lifetime . Value ;
}
}
public bool IsExpired ( )
{
return ExpiryTime . HasValue & & ExpiryTime . Value < DateTime . UtcNow ;
}
}
private readonly ConcurrentDictionary < string , CacheItem > _store ;
public Cached ( )
{
_store = new ConcurrentDictionary < string , CacheItem > ( ) ;
}
public void Set ( string key , T value , TimeSpan ? lifetime = null )
{
Ensure . That ( ( ) = > key ) . IsNotNullOrWhiteSpace ( ) ;
_store [ key ] = new CacheItem ( value , lifetime ) ;
}
public T Find ( string key )
{
CacheItem value ;
_store . TryGetValue ( key , out value ) ;
if ( value = = null )
{
return default ( T ) ;
}
if ( value . IsExpired ( ) )
{
_store . TryRemove ( key , out value ) ;
return default ( T ) ;
}
return value . Object ;
}
public T Get ( string key , Func < T > function , TimeSpan ? lifeTime = null )
{
Ensure . That ( ( ) = > key ) . IsNotNullOrWhiteSpace ( ) ;
CacheItem cacheItem ;
T value ;
if ( ! _store . TryGetValue ( key , out cacheItem ) | | cacheItem . IsExpired ( ) )
{
value = function ( ) ;
Set ( key , value , lifeTime ) ;
}
else
{
value = cacheItem . Object ;
}
return value ;
}
public void Clear ( )
{
_store . Clear ( ) ;
}
public ICollection < T > Values
{
get
{
return _store . Values . Select ( c = > c . Object ) . ToList ( ) ;
}
}
}
}