using System;
using System.Collections.Generic;
namespace Chernobyl.Creation
{
///
/// An that caches the results from another
/// and returns the cache result if a request matches a
/// cached item.
///
public class CacheFactory : Builder, IFactory
{
/// The instance that creates keys for items
/// that are to be cached or found.
/// The instance used to create items if a cached
/// item cannot be found and returned.
public CacheFactory(Func keyCreator, IFactory factory)
: this(keyCreator, factory, new Dictionary())
{}
///
/// Initializes a new instance of the class.
///
/// The instance that creates keys for items
/// that are to be cached or found.
/// The instance used to create items if a cached
/// item cannot be found and returned.
/// The instance where cached items are stored.
public CacheFactory(Func keyCreator, IFactory factory, IDictionary cache)
{
keyCreator.ThrowIfNull("keyCreator");
_keyCreator = keyCreator;
factory.ThrowIfNull("factory");
_factory = factory;
cache.ThrowIfNull("cache");
_cache = cache;
}
///
public TResult Create(T1 arg1)
{
TKey key = _keyCreator(arg1);
if (!_cache.TryGetValue(key, out var result))
{
// We do not have this instance cached. Have the factory create a new instance and report it.
result = _factory.Create(arg1);
_cache[key] = result;
}
ReportCreation(new CreationEventArgs(result, arg1));
return result;
}
///
/// The instance that creates keys for items that are to be cached or
/// found.
///
readonly Func _keyCreator;
///
/// The instance used to create items if a cached item cannot be found
/// and returned.
///
readonly IFactory _factory;
///
/// The instance where cached items are stored.
///
readonly IDictionary _cache;
}
}