gpt4 book ai didi

protobuf-net - 序列化一棵树 “The type cannot be changed once a serializer has been generated”

转载 作者:行者123 更新时间:2023-12-04 14:38:52 29 4
gpt4 key购买 nike

我尝试序列化一棵由 Craft 或 Reagent 组成的树:

[ProtoContract]
[ProtoInclude(1, typeof(Craft))]
[ProtoInclude(2, typeof(Reagent))]
public interface IReagent : IEquatable
{
[ProtoMember(1)]
int ItemId { get; set; }
[ProtoMember(2)]
int Quantity { get; set; }
}<p></p>

<p>[ProtoContract]
public class Reagent : IReagent
{
[ProtoMember(1)]
public int ItemId { get; set; }
[ProtoMember(2)]
public int Quantity { get; set; }
}</p>

<p>[ProtoContract]
public class Craft : IReagent
{
[ProtoMember(1)]
public int Skill { get; set; }</p>

<pre><code>[ProtoMember(2)]
public Profession Profession { get; set; }

[ProtoMember(3)]
public List<IReagent> Reagents { get; set; }

[ProtoMember(4)]
public int ItemId { get; set; }

[ProtoMember(5)]
public int Quantity { get; set; }
</code></pre>

<p>}
</p>

序列化代码:

public class ProtobufMessageSerializer<T> : ISerializer<T> {
private readonly ILog logger;

public ProtobufMessageSerializer(ILog logger)
{
this.logger = logger;
}

public byte[] Serialize(T entity)
{
byte[] message = new byte[0];

try
{
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, entity);
message = ms.ToByteArray();
}


logger.Info(string.Format("Serialized message with a length of: {0}", message.GetHumanReadableSize()));
}
catch (Exception ex)
{
logger.Warn(ex);
}


return message;
}

public T Deserialize(byte[] message)
{
T result = default(T);

try
{
using (var ms = new MemoryStream(message))
{
result = Serializer.Deserialize<T>(ms);
}

}
catch (Exception ex)
{
logger.Warn(ex);
}


return result;
}
}

测试代码:


[Test]
public void TestSerializer()
{
var responseSerializer = container.Resolve<ISerializer<IReagent>>();
var repos = container.Resolve<CraftRepository>();
var craft = repos.GetAll().First();

var serializedForm = responseSerializer.Serialize(craft);
var deserializedForm = responseSerializer.Deserialize(serializedForm);

Assert.NotNull(deserializedForm);
}

序列化后我得到:

一旦为 Bargains.Data.Craft (Bargains.Data.IReagent) 生成了序列化程序,就不能更改类型

堆栈跟踪:

at ProtoBuf.Meta.MetaType.ThrowIfFrozen() in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 256
at ProtoBuf.Meta.MetaType.AddSubType(Int32 fieldNumber, Type derivedType) in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 70
at ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour() in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 432
at ProtoBuf.Meta.RuntimeTypeModel.FindOrAddAuto(Type type, Boolean demand, Boolean addWithContractOnly, Boolean addEvenIfAutoDisabled) in C:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 202
at ProtoBuf.Meta.RuntimeTypeModel.GetKey(Type type, Boolean demand, Boolean getBaseKey) in C:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 369

最佳答案

基本上,接口(interface)支持目前只扩展到成员;我应该以这种方式使用 serialzie/deserialize 错误,或者让它工作! (后者显然更可取)。

如果您引入包装器,例如:

[ProtoContract]
public class Wrapper {
[ProtoMember(1)]
public IReagent Reagent {get;set;}
}

并序列化那个,然后它应该可以工作。您还需要修复以下损坏的契约(Contract):

[ProtoContract]
[ProtoInclude(1, typeof(Craft))]
[ProtoInclude(2, typeof(Reagent))]
public interface IReagent
{
[ProtoMember(3)] // <==== was 1
int ItemId { get; set; }
[ProtoMember(4)] // <==== was 2
int Quantity { get; set; }
}

(单个类型内的数字不能重复)

关于protobuf-net - 序列化一棵树 “The type cannot be changed once a serializer has been generated”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9735001/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com