Yes, it does. Json.NET在其IContractResolver
个类DefaultContractResolver
和CamelCasePropertyNamesContractResolver
中缓存类型序列化信息.除非指定自定义合同解析程序,否则将缓存并重用此信息.
For DefaultContractResolver
a global static instance is maintained internally that Json.NET uses whenever the application does not specify its own contract resolver. CamelCasePropertyNamesContractResolver
, on the other hand, maintains static tables that are shared across all instances. (I believe the inconsistency arises from legacy issues; see here for details.)
Both of these types are designed to be fully thread-safe so sharing between threads should not be a problem.
如果 Select 实现和实例化您自己的协定解析器,则只有在缓存和重用协定解析器实例本身的情况下,才会缓存和重用类型信息.因此,NewtonSoft recommends:
For performance you should create a contract resolver once and reuse instances when possible. Resolving contracts is slow and implementations of IContractResolver typically cache contracts.
If memory consumption is a problem无论出于何种原因,您需要最小化缓存契约永久占用的内存,您都可以构造自己的本地实例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)
// To reduce memory footprint, do not cache contract information in the global contract resolver.
settings.ContractResolver = new DefaultContractResolver();
try
{
return JsonConvert.SerializeObject(obj, settings);
}
finally
{
if (reset)
settings.ContractResolver = null;
}
}
}
如果您使用的是CamelCasePropertyNamesContractResolver
,请使用适当的naming strategy切换到DefaultContractResolver
,例如:
settings.ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() };
大多数高速缓存的契约存储器(100)最终将被垃圾收集.当然,通过这样做,serialization performance may suffer substantially.(包含关于例如enum
种类型和数据协定属性的反映信息的一些表是全局共享的,而不是回收的.)
For further information看牛顿软件公司的Performance Tips: Reuse Contract Resolver.