可靠集合(队列)值存储一些复杂类型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 属性或将其添加到传递给的已知类型列表中 串行器。
我该如何解决?
答案 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]。但是,有一些选项可以支持这一点:
使用包装器合约声明已知类型。
[DataContract]
[KnownType(typeof(SomeUnit))]
public class Wrapper
{
[DataMember]
public IUnit Value { get; set; }
}
[DataContract]
public class SomeUnit : IUnit
{
...
}
为DataContractSerializer constructor指定已知类型。
但是,这需要您tell service fabric to use your custom serializer。
将配置文件(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();
}
}