Ejemplo n.º 1
0
        /// <inheritdoc />
        public async Task <CacheResult <TValue> > GetOrCreateAsync(string key, Func <ICacheEntryContext, Task <TValue> > factory)
        {
            using var keyLock = await _keys
                                .GetOrAdd(key, k => new SemaphoreSlim(1))
                                .WaitAsyncAndGetLockReleaser();

            CacheItem <TValue> cacheItem;
            CacheHitMiss       cacheHitMiss = CacheHitMiss.Miss;
            bool isCached = false;

            if (_memoryCache.TryGetValue(key, out object result))
            {
                // from cache
                cacheItem    = (CacheItem <TValue>)result;
                cacheHitMiss = CacheHitMiss.Hit;
                isCached     = true;
            }
            else
            {
                // add new to cache
                var cacheEntry = _memoryCache.CreateEntry(key);

                var cacheEntryContext = new CacheEntryContext(_cacheSectionDescriptor, cacheEntry);
                var sw = Stopwatch.StartNew();

                try
                {
                    TValue  value       = default;
                    Message?message     = null;
                    bool?   shouldCache = null;

                    try
                    {
                        // Create value with factory
                        value = await factory(cacheEntryContext);

                        // Optionally can check whether value is valid and get error message
                        if (Settings.Validate != null)
                        {
                            var validationContext = new ValidationContext <TValue>(_cacheSectionDescriptor, value, cacheEntryContext.Metadata);
                            Settings.Validate(validationContext);

                            message     = validationContext.Error;
                            shouldCache = validationContext.ShouldCache;
                        }
                    }
                    catch (Exception e)
                    {
                        if (Settings.HandleError != null)
                        {
                            var errorHandleContext = new ErrorHandleContext <TValue>(_cacheSectionDescriptor, e, cacheEntryContext.Metadata)
                            {
                                Error       = CreateErrorMessage(),
                                Value       = default,
 /// <summary>
 /// Initializes a new instance of the <see cref="CacheResult{TValue}"/> struct.
 /// </summary>
 public CacheResult(
     ICacheSectionDescriptor <TValue> cacheSection,
     string key,
     TValue value,
     Message?error,
     IPropertyContainer metadata,
     CacheHitMiss hitMiss,
     bool isCached)
 {
     SectionName = cacheSection.SectionName;
     Settings    = cacheSection.CacheSettings;
     Key         = key;
     Value       = value;
     Error       = error;
     Metadata    = metadata;
     HitMiss     = hitMiss;
     IsCached    = isCached;
 }