/// <summary>
 /// Initializes a new instance of the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
 /// class that contains elements copied from the specified <see cref="System.Collections.Generic.IDictionary<string, T>"/>
 /// and uses the default equality comparer for the key type.
 /// </summary>
 /// <param name="dictionary">The <see cref="System.Collections.Generic.IDictionary<string, T>"/> whose elements are
 /// copied to the new <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>.</param>
 /// <param name="cacheDir">The on-disk directory where objects are cached.</param>
 /// <param name="cachingType">How/when items are cached/uncached.</param>
 /// <exception cref="System.ArgumentNullException">dictionary is null.</exception>
 /// <exception cref="System.ArgumentException">dictionary contains one or more duplicate keys.</exception>
 public MultiLevelCache(IDictionary <string, T> dictionary,
                        string cacheDir = DEFAULT_DISK_CACHE_DIR,
                        CacheInitOption cacheCreationOption = DEFAULT_CACHE_CREATION_OPTION,
                        CacheType cachingType = DEFAULT_CACHING_TYPE)
     : this(dictionary, null, cacheDir, cacheCreationOption, cachingType)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
 /// class that is empty, has the default initial capacity, and uses the specified
 /// <see cref="System.Collections.Generic.IEqualityComparer<string>"/>.
 /// </summary>
 /// <param name="comparer">The <see cref="System.Collections.Generic.IEqualityComparer<string>"/> implementation to use
 /// when comparing keys, or null to use the default <see cref="System.Collections.Generic.EqualityComparer<string>"/>
 /// for the type of the key.</param>
 /// <param name="cacheDir">The on-disk directory where objects are cached.</param>
 /// <param name="cachingType">How/when items are cached/uncached.</param>
 public MultiLevelCache(
     IEqualityComparer <string> comparer,
     string cacheDir = DEFAULT_DISK_CACHE_DIR,
     CacheInitOption cacheCreationOption = DEFAULT_CACHE_CREATION_OPTION,
     CacheType cachingType = DEFAULT_CACHING_TYPE)
     : this(0, comparer, cacheDir, cacheCreationOption, cachingType)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
 /// class that is empty, has the specified initial capacity, and uses the default
 /// equality comparer for the key type.
 /// </summary>
 /// <param name="capacity">The initial number of elements that the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
 /// can contain.</param>
 /// <param name="cacheDir">The on-disk directory where objects are cached.</param>
 /// <param name="cachingType">How/when items are cached/uncached.</param>
 public MultiLevelCache(
     int capacity,
     string cacheDir = DEFAULT_DISK_CACHE_DIR,
     CacheInitOption cacheCreationOption = DEFAULT_CACHE_CREATION_OPTION,
     CacheType cachingType = DEFAULT_CACHING_TYPE)
     : this(capacity, null, cacheDir, cacheCreationOption, cachingType)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
 /// class that contains elements copied from the specified System.Collections.Generic.IDictionary<TKey,TValue>
 /// and uses the specified System.Collections.Generic.IEqualityComparer<T>.
 /// </summary>
 /// <param name="dictionary">The <see cref="System.Collections.Generic.IDictionary<string, T>"/> whose elements are
 /// copied to the new <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>.</param>
 /// <param name="comparer">The <see cref="System.Collections.Generic.IEqualityComparer<string>"/> implementation to use
 /// when comparing keys, or null to use the default <see cref="System.Collections.Generic.EqualityComparer<string>"/>
 /// for the type of the key.</param>
 /// <param name="cacheDir">The on-disk directory where objects are cached.</param>
 /// <param name="cachingType">How/when items are cached/uncached.</param>
 /// <exception cref="System.ArgumentNullException">dictionary is null.</exception>
 /// <exception cref="System.ArgumentException">dictionary contains one or more duplicate keys.</exception>
 public MultiLevelCache(
     IDictionary <string, T> dictionary,
     IEqualityComparer <string> comparer,
     string cacheDir = DEFAULT_DISK_CACHE_DIR,
     CacheInitOption cacheCreationOption = DEFAULT_CACHE_CREATION_OPTION,
     CacheType cachingType = DEFAULT_CACHING_TYPE)
     : this((dictionary != null) ? dictionary.Count : 0, comparer, cacheDir, cacheCreationOption, cachingType)
 {
 }
        /// <summary>
        /// Sets up the storage cache directories. For reading and writing.
        /// </summary>
        /// <param name="path">A path where to initializer the directories.</param>
        /// <param name="createOps">The create options of </param>
        private async void Storage_Init(string path, CacheInitOption createOps)
        {
            try
            {
                var rootDir = ApplicationData.Current.LocalFolder;
                var fldr    = StorageFolder.GetFolderFromPathAsync(path);
                _cacheRoot = await rootDir.CreateFolderAsync(
                    path,
                    createOps == CacheInitOption.ReplaceExisting
                    ?CreationCollisionOption.ReplaceExisting
                    : CreationCollisionOption.OpenIfExists);

                /// Reads the values in the storage cache.
                /// If deferred loading is activated, only the names
                /// of the items in storage are read, otherwise,
                /// the items are deserialized.
                bool immediate = (CachingType == CacheType.ImmediateCaching);
                var  files     = await _cacheRoot.GetFilesAsync();

                foreach (var file in files)
                {
                    var keyName = file.Name;
                    var item    = new CacheItem <T> {
                        KeyName = keyName, InStorage = true, InMemory = immediate
                    };
                    if (immediate)
                    {
                        // Read entire file
                        Storage_Read(item);
                    }
                    else
                    {
                        // Just put names and default values so we know they exist.
                        _dictionary.Add(keyName, item.Value);
                        _items.Add(keyName, item);
                    }
                }
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
        /// class that is empty, has the specified initial capacity, and uses the specified
        /// <see cref="System.Collections.Generic.IEqualityComparer<string>"/>.
        /// </summary>
        /// <param name="capacity">The initial number of elements that the <see cref="DapperApps.Phone.Collections.MultiLevelCache<T>"/>
        /// can contain.</param>
        /// <param name="comparer">The <see cref="System.Collections.Generic.IEqualityComparer<string>"/> implementation to use
        /// when comparing keys, or null to use the default <see cref="System.Collections.Generic.EqualityComparer<string>"/>
        /// for the type of the key.</param>
        /// <param name="cacheDir">The on-disk directory where objects are cached.</param>
        /// <param name="cachingType">How/when items are cached/uncached.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">capacity is less than 0.</exception>
        public MultiLevelCache(
            int capacity,
            IEqualityComparer <string> comparer,
            string cacheDir = DEFAULT_DISK_CACHE_DIR,
            CacheInitOption cacheCreationOption = DEFAULT_CACHE_CREATION_OPTION,
            CacheType cachingType = DEFAULT_CACHING_TYPE)
        {
            try
            {
                _dictionary = new Dictionary <string, T>(capacity, comparer);
                _items      = new Dictionary <string, CacheItem <T> >(capacity, comparer);

                CachingType = cachingType;

                //TODO exceptions
                Storage_Init(cacheDir, cacheCreationOption);
            }
            catch
            {
                throw;
            }
        }