是的,它会。Json.NET 将类型序列化信息缓存在其
IContractResolver
类
DefaultContractResolver
和
CamelCasePropertyNamesContractResolver
中。除非您指定自定义合同解析器,否则将缓存并重复使用此信息。
对于
DefaultContractResolver
,在应用程序未指定其自己的合同解析器时,内部维护全局静态实例,Json.NET 将使用它。另一方面,
CamelCasePropertyNamesContractResolver
维护静态表,在所有实例之间共享。(我认为这种不一致性来源于遗留问题,请参见
此处了解详情。)
这两种类型都被设计为完全线程安全的,因此在线程之间共享不应该是一个问题。
如果您选择实现和实例化自己的合同解析器,则只有缓存和重用合同解析器实例本身时,类型信息才会被缓存和重用。 因此,Newtonsoft 建议:
为了提高性能,应该创建一个合同解析器并尽可能重复使用实例。 解析合同很慢,而且 IContractResolver 的实现通常会缓存合同。
如果内存消耗是一个问题,并且由于某种原因您需要最小化缓存合同所占用的永久内存,您可以构造自己的本地实例 DefaultContractResolver
(或某些自定义子类),使用它进行序列化,然后立即删除所有对它的引用,例如:
public class JsonExtensions
{
public static string SerializeObjectNoCache<T>(T obj, JsonSerializerSettings settings = null)
{
settings = settings ?? new JsonSerializerSettings();
bool reset = (settings.ContractResolver == null);
if (reset)
settings.ContractResolver = new DefaultContractResolver();
try
{
return JsonConvert.SerializeObject(obj, settings);
}
finally
{
if (reset)
settings.ContractResolver = null;
}
}
}
如果您正在使用 CamelCasePropertyNamesContractResolver
,请切换到适当的命名策略,例如 DefaultContractResolver
:
settings.ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }
大多数缓存的合同内存(
但并非全部)最终将被垃圾回收。当然,这样做会导致
序列化性能显著下降。(某些包含有关例如
枚举
类型和数据合同属性的反射信息的表格是全局共享的,不会被回收。)
更多信息请参见Newtonsoft的
性能提示:重用合同解析器。