/// <summary> /// Initializes a new instance of the <see cref="ReferenceCountingCacheItemProxy" /> class. /// </summary> /// <param name="cacheItem"> /// The cache item that this proxy will used to access the underlying object represented. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="cacheItem" /> is <see langword="null" />. /// </exception> // Disabled warning about non-null member (_cacheItem) being set as it will always be set before use. // ReSharper disable once NotNullMemberIsNotInitialized protected ReferenceCountingCacheItemProxy( [JetBrains.Annotations.NotNull] ReferenceCountingCacheItem <TKey, TItem, TProxy> cacheItem) { cacheItem.Validate(nameof(cacheItem), ObjectIs.NotNull); _cacheItem = cacheItem; _cacheItem.AddReference(); _token = _cacheItem.Token; }
public TProxy this[[JetBrains.Annotations.NotNull] TKey key] { get { CheckNotDisposed(); key.Validate(nameof(key), ObjectIs.NotNull); // Our first attempt is from outside any locking ReferenceCountingCacheItem <TKey, TItem, TProxy> cachedItem; if (!_cache.TryGetValue(key, out cachedItem)) { // No luck? Then get exclusive access and try again. _lock.EnterWriteLock(); try { // Someone else was in the process of creating it when we entered the lock. if (!_cache.TryGetValue(key, out cachedItem)) { // Still no luck, then we will need to create a cache entry cachedItem = new ReferenceCountingCacheItem <TKey, TItem, TProxy>(_createItem, key); _cache.Add(key, cachedItem); cachedItem.CacheItemDisposed += CachedItemDisposed; } } finally { _lock.ExitWriteLock(); } } Debug.Assert(cachedItem != null, "cachedItem != null"); // Call the GetItem method from outside any locking - it will perform its own locking internally until // the item has been created. var proxy = _proxyFactory(cachedItem); if (proxy == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.Exceptions.DelegateReturnedNull, "_proxyFactory")); } proxy.ProxyFactory = _proxyFactory; return(proxy); } }