YamlDotNet的IDeserializer可以作为IServiceCollection中的单例使用吗?

问题描述 投票:0回答:2

我正在配置一个 YamlDotNet 反序列化器,如下所示:

static IDeserializer CreateYamlDeserializer()
{
    var deserializer = new DeserializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .WithTypeConverter(new YamlEnumMemberAttributeConverter())
    .IgnoreUnmatchedProperties()
    .Build();
    return deserializer;
}

然后我有 3 个不同的解析器,都需要通过构造函数注入反序列化器。

将反序列化器注册为单例是否安全,或者考虑到解析器可以并行运行,每个服务都需要自己的实例(瞬态)吗?

services.AddSingleton<IDeserializer>(CreateYamlDeserializer());
// or: services.AddTransient<IDeserializer>(provider => CreateYamlDeserializer());
services.AddSingleton<YamlParserA>();
services.AddSingleton<YamlParserB>();
services.AddSingleton<YamlParserC>();
dependency-injection yamldotnet
2个回答
4
投票

序列化器和反序列化器是线程安全的,可以(并且应该)用作单例。


0
投票

@AntoineAubry 我已经开始收到几个这样的异常:

System.InvalidOperationException:'更改的操作 非并发集合必须具有独占访问权限。并发 对此集合执行了更新并破坏了其状态。这 集合的状态不再正确。'

正如 @alxmitch 在下面的问题中所述,序列化/反序列化目前不是线程安全的。

https://github.com/aaubry/YamlDotNet/issues/921

有一个 PR 可以使其线程安全:

https://github.com/aaubry/YamlDotNet/pull/920

在线程安全之前,我使用每个线程的序列化器/反序列化器

ThreadLocal<T>
。也可与
INodeDeserializer
配合使用。

private static readonly ThreadLocal<IDeserializer> Deserializer = new(() =>
  new DeserializerBuilder()
  .WithNamingConvention(CamelCaseNamingConvention.Instance)
  .WithNodeDeserializer(inner => new ValidatingNodeDeserializer(inner), s => s.InsteadOf<ObjectNodeDeserializer>())
  .Build()
);

Deserializer.Value.Deserialize<T>(inputValue);

https://github.com/aaubry/YamlDotNet/discussions/844

https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadlocal-1?view=net-8.0&redirectedfrom=MSDN

https://github.com/aaubry/YamlDotNet/blob/master/YamlDotNet.Samples/ValidatingDuringDeserialization.cs

© www.soinside.com 2019 - 2024. All rights reserved.