FileCache实现报错:闭包类型未标记可序列化问题求助
解决FileCache委托未执行+序列化错误的问题
嘿,我来帮你搞定这个头疼的问题!你遇到的「类型未标记为可序列化」错误,以及委托没执行的情况,根源其实是同一个——.NET自动生成的匿名捕获类没被标记可序列化,导致FileCache处理缓存时直接报错中断了。
问题到底出在哪?
当你在缓存的GetOrAdd方法里用了捕获外部变量的委托(比如你的generateString方法如果依赖控制器里的实例变量,或者你是用匿名委托写的逻辑),.NET会偷偷生成一个叫<>c__DisplayClass0_0的匿名类来存这些捕获的变量。但这个自动生成的类默认没有[Serializable]特性,而FileCache在处理缓存项时需要序列化相关对象,自然就抛出错误了,委托也因为序列化失败根本没机会执行。
几个靠谱的解决办法
1. 把生成方法改成静态(最省事)
如果你的generateString不需要依赖控制器的实例变量,直接把它改成静态方法,这样委托就不会捕获任何实例上下文,也就不会生成那个麻烦的匿名类:
private static string generateString(int? Id) { return "String"; }
之后调用缓存时直接传这个静态方法的委托就行,完美避开序列化问题。
2. 手动写个可序列化的逻辑类(适合需要捕获变量的场景)
要是必须用到控制器里的变量(比如依赖某个服务),那就自己定义一个带[Serializable]标记的类,把逻辑和需要的变量封装进去,代替自动生成的匿名类:
[Serializable] public class StringGenerator { // 把需要捕获的依赖/变量存这里,确保这个变量本身也是可序列化的 private readonly IMyService _myService; public StringGenerator(IMyService myService) { _myService = myService; } public string Generate(int? Id) { // 这里写原来generateString的逻辑,比如用_myService做点事情 return $"Generated string for Id: {Id}, service value: {_myService.GetValue()}"; } }
然后在控制器里这么用:
var generator = new StringGenerator(this.MyService); var cachedValue = fileCache.GetOrAdd($"cache_key_{Id}", entry => generator.Generate(Id));
3. 手动拆分缓存逻辑(最稳妥的兜底方案)
要是不想折腾委托的序列化,干脆手动先检查缓存,不存在再生成添加,完全绕开委托序列化的问题:
var cacheKey = $"my_cache_key_{Id}"; var cachedResult = fileCache.Get(cacheKey) as string; if (cachedResult == null) { cachedResult = generateString(Id); // 这里可以设置缓存过期策略 fileCache.Set(cacheKey, cachedResult, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromHours(1) }); } // 直接用cachedResult就行
额外要注意的点
- 如果你缓存的是自定义对象,那这个对象本身也得标记
[Serializable],不然照样会序列化失败 - 绝对别在委托里捕获
HttpContext、控制器实例这类本身不可序列化的对象,这肯定会炸
内容的提问来源于stack exchange,提问作者ExternalUse
相关产品推荐
相关产品推荐

