ProtoBuf转换方法To / From不使用接口?

时间:2017-08-07 12:17:47

标签: c# .net protocol-buffers protobuf-net

在我的ProtoBuf序列化配置中,我有一个接口IPoint,它放在我的配置的每个模型上,可以被我配置的另一个模型引用。 我配置的每个节点都实现IConfigurationNode,这是我所有模型的根父。

我有一个Surrogate,因为在大多数情况下,IPoint被放在我的hiearchy的特定节点上,并且由于Proto不支持多重继承,我做了以下内容: / p>

[ProtoContract]
public class ConfigurationNodeSurrogate<T>
    where T : class, IConfigurationNode
{
    [ProtoMember(1, AsReference = true)]
    public IConfigurationNode ConfigurationNode { get; set; }

    [ProtoConverter]
    public static T From(ConfigurationNodeSurrogate<T> configurationNodeSurrogate)
    {
        return configurationNodeSurrogate?.ConfigurationNode as T;
    }

    [ProtoConverter]
    public static ConfigurationNodeSurrogate<T> To(T configurationNode)
    {
        return configurationNode == null ? null : new ConfigurationNodeSurrogate<T> {ConfigurationNode = configurationNode};
    }
}

我宣布它是这样的:

RuntimeTypeModel.Default.Add(typeof(IPoint), false).SetSurrogate(typeof(ConfigurationNodeSurrogate<IPoint>));

因此,它应该将其序列化为IConfigurationNode

IConfiguration以及下面的所有课程都有ProtoContract属性,他们都在注册所有可能的孩子。

当我尝试序列化整个事情时,没有问题,但是当我尝试反序列化时,我有一个例外:

System.InvalidCastException : Unable to cast object of type 'ConfigurationNodeSurrogate`1[IPoint]' to type 'IConfigurationNode'.
   at proto_518(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options)
   at proto_235(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_3(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_506(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options)
   at proto_327(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_3(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_506(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options)
   at proto_183(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_175(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_173(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_3(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_506(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options)
   at proto_233(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_3(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_506(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options)
   at proto_271(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_3(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type)
   at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader)
   at proto_506(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate)
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context)
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type)
   at ProtoBuf.Serializer.Deserialize[T](Stream source)

我觉得这与一些“IPoint”DataMember我实际上是空的这一事实有关,我不确定转换器如何处理这个问题。我的代理人是否正确实施了?

修改 我忘了提及,但我的IPoint直接继承了IConfigurationNode

编辑2 这是一个说明我的案例的例子

[ProtoContract(AsReferenceDefault =true)]
public interface IConfigurationNode {
    List<IConfigurationNode> Childs{get;set;}
}

[ProtoContract(AsReferenceDefault =true)]
public interface IPoint: IConfigurationNode{

}

[ProtoContract(AsReferenceDefault=true)]
public class SomeClass:IConfigurationNode
{
    [ProtoMember(1)]
    List<IConfigurationNode> Childs{get;set;}

    public SomeClass(){
        Childs= new List<IConfigurationNode>(); 
    }
}

[ProtoContract(AsReferenceDefault=true)]
public SomeNodeA:SomeClass, IPoint
{
}

[ProtoContract(AsReferenceDefault=true)]
public SomeNodeB: SomeClass{
    [ProtoMember(1)]
    public IPoint SomeReference{get;set;}
}



//Some test code:

SomeClass configuration = new SomeClass();
SomeNodeA nodeA = new SomeNodeA();
SomeNodeB nodeB = new SomeNodeB();
nodeB.SomeReference = nodeB;
configuration.Childs.Add(nodeA);
configuration.Childs.Add(nodeB);

byte[] bytes = ProtoBufHelper.ProtoSerialize(configuration);
SomeClass  configuration2 = ProtoBufHelper.ProtoDeserialize<SomeClass >(bytes);

EDIT3 我目前在我的解决方案中导入了ProtoBuf的代码,以便稍微调试并尝试了解发生了什么。

奇怪的是,当我试图反序列化ConfigurationNode的属性ConfigurationNodeSurrogate时,在类BclHelper中,它试图获取一个元素NetCache,这是代理(而不是预期的`IConfigurationNode。)不确定为什么。我尝试用一​​个较小的例子重现它,它确实有效。我觉得订单改变了一些东西(意思是如果同一个类之前是通过接口序列化的,或者不通过接口进行序列化)。

0 个答案:

没有答案