using DTT.Utils.Exceptions; using System; using System.Collections.Generic; namespace DTT.Utils.Optimization { /// /// A dictionary variant that allows for constructors to be added to /// delay the initial creation of a struct value to where when it is needed /// using the wrapper struct. /// /// The type of key. /// The type of the value. public class LazyValueDictionary : LazyDictionaryBase where TValue : struct { /// /// Wraps the item value and its constructor, providing /// a one time initialization upon retrieval. /// private class Container { /// /// The cached item value. It is wrapped inside a /// struct to check whether it is initialized or not. /// private TValue? _nullableValue; /// /// The constructor with which to initialize the value. /// private readonly Func _constructor; /// /// The accessor to the cached item value. It returns the value of the nullable wrapper /// if it has it. Otherwise it will assign the value using the constructor and return /// the resulting value. /// public TValue Value => _nullableValue ?? (_nullableValue = _constructor()).Value; /// /// Creates a new instance, storing the given constructor. /// /// The constructor with which to initialize the value. public Container(Func constructor) => _constructor = constructor; } /// /// Contains the keys with their value in their respective containers. /// private readonly Dictionary _values = new Dictionary(); /// /// Adds a new item to the dictionary with its respective constructor. /// /// The key for the value. /// /// The constructor with which to initialize the value. /// public void Add(TKey key, Func constructor) { if (key == null) throw new LazyDictionaryException("Name of property is null"); if (constructor == null) throw new LazyDictionaryException($"Constructor of {key} is null."); _values.Add(key, new Container(constructor)); } /// /// Should return the item value based on the given key. /// /// The key to get the value for. /// The item value. protected override TValue GetValue(TKey key) => _values[key].Value; } }