| File: Hybrid\HybridCacheEntryContext.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.Caching.Abstractions\src\Microsoft.Extensions.Caching.Abstractions.csproj (Microsoft.Extensions.Caching.Abstractions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; namespace Microsoft.Extensions.Caching.Hybrid; /// <summary> /// Provides a mutable view of the cache entry options in effect for a single <see cref="HybridCache"/> operation, /// supplied to a factory callback so that it can adjust those options based on the result of the data fetch. /// </summary> /// <remarks> /// When a <see cref="HybridCache"/> implementation constructs the context for a factory callback, it seeds the /// properties from the effective options for the operation (composed from the per-call and any global options), so /// the factory observes the current values and can change them to influence how the resulting value is cached. /// A context constructed directly reflects only whatever <see cref="HybridCacheEntryOptions"/> were supplied to /// its constructor. Implementations can use <see cref="Revision"/> to detect whether the factory changed any value. /// </remarks> public sealed class HybridCacheEntryContext { /// <summary> /// Initializes a new instance of the <see cref="HybridCacheEntryContext"/> class, seeding its values from /// the supplied options. /// </summary> /// <param name="options"> /// The options to seed the context from, or <see langword="null"/> to start with unset values. This is /// typically the effective options for the operation, so that the factory callback observes the current values. /// </param> /// <remarks> /// This is primarily intended for <see cref="HybridCache"/> implementations that need to construct a context /// to pass to a factory callback. /// </remarks> public HybridCacheEntryContext(HybridCacheEntryOptions? options) { if (options is not null) { Expiration = options.Expiration; LocalCacheExpiration = options.LocalCacheExpiration; Flags = options.Flags; LocalSize = options.LocalSize; } // Seeding from the supplied options is not a caller change, so the context starts at revision zero. Revision = 0; } /// <summary> /// Gets or sets the overall cache duration of this entry, passed to the backend distributed cache. /// </summary> public TimeSpan? Expiration { get; set { if (field != value) { field = value; BumpRevision(); } } } /// <summary> /// Gets or sets the expiration for the local (in-process) cache entry. /// </summary> /// <remarks> /// When retrieving a cached value from an external cache store, this value will be used to calculate the local /// cache expiration, not exceeding the remaining overall cache lifetime. /// </remarks> public TimeSpan? LocalCacheExpiration { get; set { if (field != value) { field = value; BumpRevision(); } } } /// <summary> /// Gets or sets additional flags that apply to the requested operation. /// </summary> public HybridCacheEntryFlags? Flags { get; set { if (field != value) { field = value; BumpRevision(); } } } /// <summary> /// Gets or sets the size to assign to entries in the local (in-process) cache. /// </summary> /// <remarks> /// The units are determined by the underlying local cache implementation. When the local cache /// is an <see cref="Memory.IMemoryCache"/> configured with a size limit, this value corresponds to /// <see cref="Memory.ICacheEntry.Size"/>. /// <para> /// When <see langword="null"/>, the implementation may compute a default size (for example, from /// the serialized payload length). /// </para> /// </remarks> public long? LocalSize { get; set { if (field != value) { field = value; BumpRevision(); } } } /// <summary> /// Gets a value that increments whenever a property on this instance is changed. /// </summary> /// <remarks> /// Implementations of <see cref="HybridCache"/> can capture this value before invoking a factory /// callback and compare it afterwards to determine whether the factory changed any value. /// The value increments only when a setter assigns a different value than the current one. /// </remarks> public int Revision { get; private set; } private void BumpRevision() { // unchecked: rollover is fine because callers compare for inequality, not ordering. unchecked { Revision++; } } internal HybridCacheEntryOptions ToOptions() => new HybridCacheEntryOptions { Expiration = Expiration, LocalCacheExpiration = LocalCacheExpiration, Flags = Flags, LocalSize = LocalSize, }; }