Service Fabric Reliable Collections:序列化问题

时间:2015-12-09 03:18:47

标签: c# serialization collections deserialization azure-service-fabric

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

我已将其标记为[DataContract],其成员为[DataMember],并在其上添加了[KnownType(typeof(SomeUnit))]属性。

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

  

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

我该如何解决?

2 个答案:

答案 0 :(得分: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!

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

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

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

[DataContract]
public class SomeUnit : BaseClass
{
    ...
}

无法在接口类型上应用[KnownType]。但是,有一些选项可以支持这一点:

选项#1

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

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

[DataContract]
public class SomeUnit : IUnit
{
    ...
}

选项#2

DataContractSerializer constructor指定已知类型。

但是,这需要您tell service fabric to use your custom serializer

选项#3

将配置文件(app.config)中的已知类型指定为described here

答案 1 :(得分:3)

我知道这是一个古老的话题但是在遇到这个问题并且不想使用KnownType方法之后(因为如果你有很多派生类型它会变得有点乱)我能成功地得到我的使用反射进行序列化的消息:

[DataContract]
[KnownType("GetKnownTypes")]
public abstract class Event
{
    [DataMember]
    public DateTime AtTime { get; private set; }

    public Event()
    {
        AtTime = DateTime.Now;
    }

    private static Type[] GetKnownTypes()
    {
        return typeof(Event).Assembly.GetTypes()
            .Where(x => x.IsSubclassOf(typeof(Event)))
            .ToArray();
    }
}