6

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

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

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

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

我该如何解决?

4

2 回答 2

8

由于您没有显示任何代码,我们只能猜测是什么原因造成的。

如果您使用具有通用项目类型的可靠队列(例如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在基类上应用 a 来解决此问题,从而显式声明反序列化程序应注意的派生类。

[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 构造函数指定已知类型。

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

选项#3

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

于 2015-12-10T12:26:49.837 回答
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();
    }
}
于 2017-08-01T14:31:14.713 回答