Service Fabric Reliable Collections:序列化问题

AsV*_*leO 5 c# collections serialization deserialization azure-service-fabric

可靠的集合(队列)值存储一些复杂的类型SomeUnit.

我已经将它标记为[DataContract]并且它是成员,[DataMember]并且[KnownType(typeof(SomeUnit))]还在其上添加了属性.

看起来现在SomeUnit序列化,但随后抛出反序列化异常:

元素'urn:ServiceFabric.Communication:item'包含映射到名称' http://schemas.datacontract.org/2004/07/RP.Core:SomeUnit ' 的类型的数据.反序列化器不知道映射到此名称的任何类型.如果使用DataContractSerializer或将与"SomeUnit"对应的类型添加到已知类型列表中,请考虑使用DataContractResolver - 例如,使用KnownTypeAttribute属性或将其添加到传递给序列化程序的已知类型列表中.

我该如何解决?

Mår*_*röm 7

由于您没有显示任何代码,我们只能猜测导致此问题的原因.

如果您将使用具有通用项类型的可靠队列(例如基类),则会发生此问题SomeUnit.

// Using reliable collection with a base item type
IReliableQueue<BaseClass> myQueue = ...;

// Store derived item in the queue
SomeUnit myData = ...; // SomeUnit inherit from BaseClass
await myQueue.EnqueueAsync(txn, myData); // OK to store but won't deserialize!
Run Code Online (Sandbox Code Playgroud)

该队列的反序列化器将知道如何解析,BaseClass但它不会隐式地知道您的派生类SomeUnit.

您可以通过KnownTypeAttribute在基类上应用a来解决这个问题,从而明确声明反序列化程序应该知道的派生类.

[DataContract]
[KnownType(typeof(SomeUnit))]
public class BaseClass
{
    ...
}

[DataContract]
public class SomeUnit : BaseClass
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

在接口类型上应用[KnownType]是不可能的.但是,有一些选项可以支持这个:

选项1

使用包装器合约声明已知类型.

[DataContract]
[KnownType(typeof(SomeUnit))]
public class Wrapper
{
    [DataMember]
    public IUnit Value { get; set; }
}

[DataContract]
public class SomeUnit : IUnit
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

选项#2

DataContractSerializer构造函数指定已知类型.

但是,这需要您告诉服务结构使用您的自定义序列化程序.

选项#3

如此处所述,在配置文件(app.config)中指定已知类型.