我正在使用
<PackageReference Include="Microsoft.Orleans.Sdk" Version="8.2.0" />
为非常简单的记录生成序列化器:
namespace BaseNamespace.OldNameSpace;
[GenerateSerializer, Alias("MyRecord")]
public sealed record MyRecord
{
[Id(0)]
public string Name{ get; set; }
[Id(1)]
public int Age { get; set; }
}
我有一个带有以下构造函数的谷物:
public sealed class MyRecordGrain([PersistentState(stateName: "MyRecordValue", MyRecordStorageKey")] IPersistentState<MyRecord> state) : IGrain, IMyRecordGrain
每次调用 Grain 时,我都会设法存储该对象并通过构造函数检索它。在 SQL Server 中,使用 select cast(PayloadBinary as varchar(MAX)), * from OrleansStorage
在
PayloadBinary列上看起来像这样:
{
"$id": "1",
"$type": "BaseNamespace.OldNameSpace.MyRecord, MyProject.Common.Model",
"Name": "Anthony",
"Age ": 14,
},
当我大量重构类库和命名空间时,问题就出现了。如果我将
MyRecord
的命名空间从 namespace BaseNamespace.OldNameSpace;
更改为 namespace BaseNamespace.NewNameSpace;
并调用grain,则存储序列化将失败并出现此错误,因为命名空间不匹配:
Error from storage provider AdoNetGrainStorage.personCache during ReadStateAsync for grain personCache/PersonCacheKey
Exc level 0: Newtonsoft.Json.JsonSerializationException: Error resolving type specified in JSON 'BaseNamespace.OldNameSpace.MyRecord, MyProject.Common.Model], System.Collections.Concurrent'. Path '$type', line 1, position 263.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolveTypeName(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, String qualifiedTypeName)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
如果我将命名空间改回
BaseNamespace.OldNameSpace
一切正常。我知道我应该向记录类添加 alias
以便它们支持不同的版本,但是如何避免此命名空间重构错误?如果我已经在grain的构造函数中提供了有关程序集和命名空间的信息,为什么序列化数据需要存储这些信息IPersistentState<MyRecord>
?
谢谢!
已回答https://github.com/dotnet/orleans/discussions/9085
必须将 JsonSerializer 配置调整为:
siloBuilder.Configure<OrleansJsonSerializerOptions>(options =>
{
options.JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
})