目录
1.1.1 / Enable interceptors on all previous registrations
1.1.2 / Auto refresh stale data
If you're a fan of assembly scanning, you can decorate the OutputCache attribute on classes & interfaces you want to cache and enable them by RegisterModule FlatwhiteBuilderInterceptModule before building the container
var builder = new ContainerBuilder();
builder
.RegisterType<BlogService>()
.AsImplementedInterfaces()
.AsSelf();
// Register other types normally
...
// Register FlatwhiteBuilderInterceptModule at the end
builder.RegisterModule<FlatwhiteBuilderInterceptModule>(); var container = builder.Build();
Flatwhite can auto refresh the stale content if you set StaleWhileRevalidate with a value greater than 0. This should be used with Duration to indicates that caches MAY serve the cached result in which it appears after it becomes stale, up to the indicated number of seconds The first call comes to the service and gets a stale cache result will also make the cache system auto refresh once in the background. So if the method is not called many times in a short period, it's better to turn on AutoRefresh to make the cache alive and refreshed as soon as it starts to be stale
public interface IBlogService{
// For method with too many cache variations because of VaryByParam settings
[OutputCache(Duration = 5, VaryByParam = "tag, from, authorId", StaleWhileRevalidate = 5)]
IEnumerable<object> Search(string tag, DateTime from, Guid authorId);
// For method with not many cache variations and data is likely to changed every 5 seconds
[OutputCache(Duration = 5, VaryByParam = "blogId", StaleWhileRevalidate = 5)]
object GetById(int blogId);
// You can turn on AutoRefresh to keep the cache active if there are limited variations of the cache
[OutputCache(Duration = 5, VaryByParam = "blogId", StaleWhileRevalidate = 5, AutoRefresh = true)]
IEnumerable<string> GetBlogCategory(); }
public interface IUserService{
[OutputCache(CacheProfile="profileName")]
object GetById(Guid userId);}
Profile setting default file name is cacheProfile.yaml located at the same folder of your app.config/web.config file and has a "yaml like" format:
-- Cache profile settings, everything is case-sensitive-- Profile nameProfile1-Two-Seconds -- Profile propertyName:propertyValue, start with a tab or 4+ empty spaces Duration:2 StaleWhileRevalidate:5 VaryByParam:packageId VaryByCustom:* AutoRefresh:true RevalidateKeyFormat:anything-about-user{userId} Web-Profile2-Three-Seconds MaxAge:3 StaleWhileRevalidate:6 VaryByParam:* VaryByHeader:UserAgent IgnoreRevalidationRequest:true
You can implement another IOutputCacheProfileProvider and set to Global.OutputCacheProfileProvider or simply change the location/name of the yaml file. At the moment, only yaml file is supported.
Even though you can use AutoRefresh or StaleWhileRevalidate to auto refresh cache data. Some time you want to remove the cache item after you call a certain method. You can use RevalidateAttribute to remove the cache item or some related cache items. Decorate the attribute on another method and the cache item will be removed once the method is invoked successfully. On example below, when you call method DisableUser, because it has the Revalidate attribute decorated with "User_{userId}" as the key format, all related cache items created for method with attribute OutputCache which has RevalidateKeyFormat = "User_{userId}" will be reset.
public interface IUserService{
[OutputCache(Duration = 2, StaleWhileRevalidate = 2, VaryByParam = "userId", RevalidateKeyFormat = "User_{userId}")]
object GetById(Guid userId);
[OutputCache(Duration = 2, VaryByParam = "userId", RevalidateKeyFormat = "User_{userId}")]
Task<object> GetByIdAsync(Guid userId);
[Revalidate("User_{userId}")]
void DisableUser(Guid userId); }
Unfortunately, this is not working for distributed services. That means the method is called on one server cannot notify the other service instances on remote servers. However, it's technically achievable to extend this filter using distributed messaging or something like that to notify remote system.