-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add .Clear() method to MemoryCache #45593
Comments
Tagging subscribers to this area: @eerhardt, @maryamariyan Issue DetailsBackground and Motivation
Many (more than twenty by looking at the number of reactions) of our customers have expressed the need of this API in #36547. So far most of them was forced to use ugly workarounds like using reflection or trimming the cache to a very small size. Proposed APInamespace Microsoft.Extensions.Caching.Memory
{
public class MemoryCache
{
+ public void Clear();
}
public interface IMemoryCache
{
+ void Clear();
}
} Usage Examplesvar cache = new MemoryCache(new MemoryCacheOptions());
cache.Set("key1", "value1");
cache.Set("key2", "value2");
cache.Clear(); RisksAdding a new method to the According to my understanding, adding it with a default empty implementation would require changing the target framework from .NET Standard 2.0 to .NET 6.0?
|
Close; default interface implementations requires targeting .NET Core 3.0+, which removes the ability to run on full-framework or Mono. |
I wonder if we could/should start moving away from the interfaces. One way of doing that would be:
public abstract class MemoryCacheBase : IMemoryCache
{
// implement all IMemoryCache methods with `abstract` methods
public abstract void Clear();
}
Thoughts? cc @Tratcher @maryamariyan @davidfowl |
Adding abstract methods to a base class is just as breaking for implementers as adding new methods to an interface. You can only do it once when introducing the new base class that nobody has derived from yet. The new methods would have to be virtual with a default implementation, not abstract. There are a lot of API requests for MemoryCache, where any one of them doesn't seem significant enough to warrant a new design, but collectively they might. Is there a comprehensive list anywhere? |
In general:
|
Wanted to link here - #44522 |
Personally, I don't like introducing interfaces that typically have a single implementation... So perhaps the first step to rely less on interfaces would be to just add |
@adamsitnik if that done so, then IMemoryCache will be redundant and it will be of no use! Because we are now started adding feature directly to MemoryCache! And somehow it might even break existing stuff dependent upon this interface as well! |
What is the actual (not hypothetical) value in having this particular abstraction? The How can we add new features to As I wrote, it's my personal opinion and I refer to @eerhardt and @maryamariyan to choose the best strategy for caching extensions. |
One big one is enabling unit testing. You can easily mock out the caching behavior. Since pieces of ASP.NET depend on Caching, having this abstraction allows for other caching implementations to be injected into the application, and ASP.NET would start using that implementation. I don't know if this is ever done in practice. Another piece of value is to limit dependencies. |
@eerhardt you have convinced me, thank you! |
I've just solved this problem for myself (I needed to reset the cache between running each scenario of my unit tests), like this: public sealed class MemoryCacheManager : IMemoryCache
{
readonly IOptions<MemoryCacheOptions> _optionsAccessor;
IMemoryCache _inner;
public MemoryCacheManager(IOptions<MemoryCacheOptions> optionsAccessor)
{
_optionsAccessor = optionsAccessor;
_inner = new MemoryCache(_optionsAccessor);
}
public void Reset()
{
var old = _inner;
_inner = new MemoryCache(_optionsAccessor);
old.Dispose();
}
public void Dispose() => _inner.Dispose();
public ICacheEntry CreateEntry(object key) => _inner.CreateEntry(key);
public void Remove(object key) => _inner.Remove(key);
public bool TryGetValue(object key, out object value) => _inner.TryGetValue(key, out value);
} And then in app startup: services.Remove(services.Single(x => x.ServiceType == typeof(IMemoryCache)));
services.AddSingleton<MemoryCacheManager>();
services.AddSingleton<IMemoryCache>(provider => provider.GetRequiredService<MemoryCacheManager>()); Then I can just resolve an instance of |
namespace Microsoft.Extensions.Caching.Memory
{
partial class MemoryCache
{
public void Clear();
}
} |
Can the DIM be added only for compatible targets? |
How would that work? |
e.g. Cross target the package to netstandard and net5.0 and only add the DIMs for net5.0. |
And what would the DIM do? throw? |
If not overridden, yes. |
Background and Motivation
MemoryCache
gives the possibility to add and remove a single cache entry, but it does not allow for clearing the entire cache at once.Many (more than twenty by looking at the number of reactions) of our customers have expressed the need of this API in #36547.
So far most of them was forced to use ugly workarounds like using reflection or trimming the cache to a very small size.
Proposed API
Usage Examples
Risks
Adding a new method to the
IMemoryCache
interface is going to break users who implemented their own cache. This should be rare.According to my understanding, adding it with a default empty implementation would require changing the target framework from .NET Standard 2.0 to .NET 6.0?
The text was updated successfully, but these errors were encountered: