Summary
Ship a cache behavior over IMemoryCache or HybridCache, and a memoizer whose entries live on the stunt instance. A process-wide dictionary is the wrong store: a shared cache was dropped from Enterprise Library because entries leaked across objects.
API
- Cache behavior: an
IMemoryCache or HybridCache, plus a key selector over the invocation. The default key is the member and the argument values.
- Memoizer: stores results for that stunt only. Dropping the stunt drops the entries.
Behavior
- Skip
void members and members with ref or out parameters.
- Take a stampede lock so concurrent callers for one key share one execution.
- Store the unwrapped result of
Task<T> or ValueTask<T>. A hit returns a completed awaitable of the same declared kind.
- Failures stay uncached unless the caller opts in.
- Sit inside the retry attempt, so a failed attempt is not stored and a later success is.
Acceptance
- Two calls with the same key invoke the target once.
- Concurrent callers for one key invoke the target once.
- A
void method and a method with a ref parameter always reach the target.
- A second stunt does not see the first stunt's memoized values.
Composition
Outer to inner: observation, resilience, transaction, cache, target.


Summary
Ship a cache behavior over
IMemoryCacheorHybridCache, and a memoizer whose entries live on the stunt instance. A process-wide dictionary is the wrong store: a shared cache was dropped from Enterprise Library because entries leaked across objects.API
IMemoryCacheorHybridCache, plus a key selector over the invocation. The default key is the member and the argument values.Behavior
voidmembers and members withreforoutparameters.Task<T>orValueTask<T>. A hit returns a completed awaitable of the same declared kind.Acceptance
voidmethod and a method with arefparameter always reach the target.Composition
Outer to inner: observation, resilience, transaction, cache, target.