I'm trying to implement FileCache (https://github.com/acarteas/FileCache) which is based on ObjectCache. I'm trying to check a cache object for its existence, or add it if required and return. When the object does not exist however, the delegate is not executed and an error is thrown: Type 'myNamespace.Controllers.ListController+<>c__DisplayClass0_0' in [...] is not marked as serializable.
What I've tried (simplified):
private string generateString(int? Id)
{
return "String";
}
public ActionResult GetSomething(int? Id)
{
var cacheFilePath = $"{AppDomain.CurrentDomain.BaseDirectory}{"\\cache"}";
var cache = new FileCache(cacheFilePath, false, TimeSpan.FromSeconds(30));
if (purgeCache)
cache.Remove($"CacheKey{Id}");
Func<string> createString = () => generateString(Id);
var myString = (string) cache.AddOrGetExisting($"CacheKey{Id}", createString, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30) });
return new JsonStringResult(myString);
}
Ok, now I've tried to specify the delegate createString with Serializable, but that doesn't work. Could someone point me into the right direction?
Essentially I want: - run a statement that returns a previous output of generateString(123); if it doesn't exist or is expired, it should re-generate it.
Thanks for any tips!
Due to the nature of FileCache
, I think the only reasonable way to do that is to fallback to the usual way - check if item exists in cache and if not - add it:
private static readonly _cacheLock = new object();
private static readonly FileCache _cache = new FileCache($"{AppDomain.CurrentDomain.BaseDirectory}{"\\cache"}", false, TimeSpan.FromSeconds(30));
/// ...
lock (_cacheLock) {
var myString = _cache.Get($"CacheKey{Id}");
if (myString == null) {
myString = generateString(Id);
_cache.Set($"CacheKey{Id}", myString, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30) });
}
}
Lock is necessary because FileCache
both writes and reads from the same file, and this is never safe to do from multiple threads.