Func<string> DoSomething:类型 [...] Controller+<>c__DisplayClass0_0 未标记为可序列化
Func<string> DoSomething: Type [...] Controller+<>c__DisplayClass0_0 is not marked as serializable
我正在尝试实现基于 ObjectCache 的 FileCache (https://github.com/acarteas/FileCache)。
我正在尝试检查缓存对象是否存在,或者在需要时添加它 return。但是,当对象不存在时,不会执行委托并抛出错误:Type 'myNamespace.Controllers.ListController+<>c__DisplayClass0_0' in [...] is not marked as serializable.
我尝试过的(简化):
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);
}
好的,现在我已经尝试用 Serializable 指定委托 createString,但这不起作用。
有人能指出我正确的方向吗?
基本上我想要:
- 运行 声明 return 是 generateString(123) 的先前输出;如果它不存在或已过期,它应该重新生成它。
感谢任何提示!
AddOrGetExisting
的签名说第二个参数是 object value
而不是回调委托:
https://github.com/acarteas/FileCache/blob/master/src/FileCache/FileCache.cs
public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
我想你只是想要这个(我也纠正了你代码中的其他潜在问题):
public ActionResult GetSomething(int? id)
{
String cacheFilePath = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "Cache" );
FileCache cache = new FileCache( cacheFilePath, false, TimeSpan.FromSeconds(30) );
String cacheKey = String.Format( CultureInfo.InvariantCulture, "CacheKey{0}", id );
if( purgeCache ) cache.Remove( cacheKey );
String valueString = this.GenerateString( id );
String myString = (String)cache.AddOrGetExisting( cacheKey, valueString, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30) });
return new JsonStringResult( myString );
}
- C# 内插字符串
$"like {this}"
不适合在 UI 代码之外使用,因为它们会自动使用 CultureInfo.CurrentCulture
,这会导致输出不一致,具体取决于 ASP.NET 自动设置为访问者浏览器的 Accept-Language
header 值。最好改用显式 String.Format( CultureInfo.InvariantCulture, format, args )
。
- 您的代码在生成缓存键时有冗余步骤,我将其移至单个变量
cacheKey
。
- C# 命名约定对参数和局部变量使用
camelCase
,对方法使用 PascalCase
。
由于 FileCache
的性质,我认为唯一合理的方法是回退到通常的方式 - 检查缓存中是否存在项目,如果不存在 - 添加它:
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) });
}
}
锁定是必要的,因为 FileCache
写入和读取同一个文件,并且从多个线程执行此操作永远不安全。
我正在尝试实现基于 ObjectCache 的 FileCache (https://github.com/acarteas/FileCache)。 我正在尝试检查缓存对象是否存在,或者在需要时添加它 return。但是,当对象不存在时,不会执行委托并抛出错误:Type 'myNamespace.Controllers.ListController+<>c__DisplayClass0_0' in [...] is not marked as serializable.
我尝试过的(简化):
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);
}
好的,现在我已经尝试用 Serializable 指定委托 createString,但这不起作用。 有人能指出我正确的方向吗?
基本上我想要: - 运行 声明 return 是 generateString(123) 的先前输出;如果它不存在或已过期,它应该重新生成它。
感谢任何提示!
AddOrGetExisting
的签名说第二个参数是 object value
而不是回调委托:
https://github.com/acarteas/FileCache/blob/master/src/FileCache/FileCache.cs
public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
我想你只是想要这个(我也纠正了你代码中的其他潜在问题):
public ActionResult GetSomething(int? id)
{
String cacheFilePath = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "Cache" );
FileCache cache = new FileCache( cacheFilePath, false, TimeSpan.FromSeconds(30) );
String cacheKey = String.Format( CultureInfo.InvariantCulture, "CacheKey{0}", id );
if( purgeCache ) cache.Remove( cacheKey );
String valueString = this.GenerateString( id );
String myString = (String)cache.AddOrGetExisting( cacheKey, valueString, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30) });
return new JsonStringResult( myString );
}
- C# 内插字符串
$"like {this}"
不适合在 UI 代码之外使用,因为它们会自动使用CultureInfo.CurrentCulture
,这会导致输出不一致,具体取决于 ASP.NET 自动设置为访问者浏览器的Accept-Language
header 值。最好改用显式String.Format( CultureInfo.InvariantCulture, format, args )
。 - 您的代码在生成缓存键时有冗余步骤,我将其移至单个变量
cacheKey
。 - C# 命名约定对参数和局部变量使用
camelCase
,对方法使用PascalCase
。
由于 FileCache
的性质,我认为唯一合理的方法是回退到通常的方式 - 检查缓存中是否存在项目,如果不存在 - 添加它:
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) });
}
}
锁定是必要的,因为 FileCache
写入和读取同一个文件,并且从多个线程执行此操作永远不安全。