Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;已添加具有相同密钥的项";protobuf网络错误_C#_Dictionary_Protocol Buffers_Protobuf Net - Fatal编程技术网

C# &引用;已添加具有相同密钥的项";protobuf网络错误

C# &引用;已添加具有相同密钥的项";protobuf网络错误,c#,dictionary,protocol-buffers,protobuf-net,C#,Dictionary,Protocol Buffers,Protobuf Net,我试图用Marc Gravell的C#protobuf替换现有的序列化程序。我的代码是广泛的,我的目标是能够以最小的更改完成切换 我遇到了一个问题,我相信我理解它为什么会发生,但需要帮助克服——特别是一个解决方案,它需要对我已经存在的代码和类进行最少的更改。我的代码很复杂,因此我创建了以下简短示例来演示该问题: using System; using System.Collections.Generic; using System.IO; using ProtoBuf; namespace

我试图用Marc Gravell的C#protobuf替换现有的序列化程序。我的代码是广泛的,我的目标是能够以最小的更改完成切换

我遇到了一个问题,我相信我理解它为什么会发生,但需要帮助克服——特别是一个解决方案,它需要对我已经存在的代码和类进行最少的更改。我的代码很复杂,因此我创建了以下简短示例来演示该问题:

using System;
using System.Collections.Generic;
using System.IO;
using ProtoBuf;


namespace ConsoleApplication1
{
    class program_issue
    {

    [ProtoContract]
    public class Father
    {
        public Father()
        {
            sonny = new Son();
        }

        [ProtoMember(101)]
        public string Name;

        [ProtoMember(102)]
        public Son sonny;

    }

    [ProtoContract]
    public class Son
    {
        public Son()
        {
            Dict.Add(10, "ten");
        }

        [ProtoMember(103)]
        public Dictionary<int, string> Dict = new Dictionary<int, string>();
    }


    static void Main(string[] args)
    {
        Father f1 = new Father();
        f1.Name = "Hello";
        byte[] bts = PBSerializer.Serialize(typeof(Father), f1);

        Father f2;
        PBSerializer.Deserialize(bts, out f2);

    }


    public static class PBSerializer
    {
        public static byte[] Serialize(Type objType, object obj)
        {
            MemoryStream stream = new MemoryStream();
            ProtoBuf.Serializer.Serialize(stream, obj);
            string s = Convert.ToBase64String(stream.ToArray());
            byte[] bytes = stream.ToArray();
            return bytes;
        }


        public static void Deserialize(byte[] data, out Father obj)
        {
            using (MemoryStream stream = new MemoryStream(data))
            {
                obj = ProtoBuf.Serializer.Deserialize<Father>(stream);
            }

        }
    }

}
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用ProtoBuf;
命名空间控制台应用程序1
{
班级计划问题
{
[原始合同]
公课父亲
{
公父()
{
桑尼=新儿子();
}
[原成员(101)]
公共字符串名称;
[原成员(102)]
公子桑尼;
}
[原始合同]
公子
{
公子()
{
添加(10,“十”);
}
[原成员(103)]
公共字典Dict=新字典();
}
静态void Main(字符串[]参数)
{
父亲f1=新父亲();
f1.Name=“你好”;
字节[]bts=PBSerializer.Serialize(typeof(父),f1);
父亲f2;
反序列化(bts,输出f2);
}
公共静态类序列化程序
{
公共静态字节[]序列化(类型objType,对象obj)
{
MemoryStream stream=新的MemoryStream();
ProtoBuf.Serializer.Serialize(流,obj);
string s=Convert.ToBase64String(stream.ToArray());
byte[]bytes=stream.ToArray();
返回字节;
}
公共静态void反序列化(字节[]数据,输出父对象)
{
使用(内存流=新内存流(数据))
{
obj=ProtoBuf.Serializer.Deserialize(流);
}
}
}
}
}
简而言之,创建父对象时,它会创建一个子对象,该子对象使用一些值初始化字典。我假设protobuf在反序列化时尝试重建对象时使用相同的构造函数(因此也会使用值启动字典),然后作为反序列化->错误的一部分再次尝试推送相同的值

如何通过对代码进行最小的更改来克服它

亲切问候,,
Yossi.

这里最简单的选择可能是:

[ProtoContract(SkipConstructor = true)]
它不会执行构造函数(或字段初始值设定项)。请注意,如果没有数据,这将使字典为空。另一种方法可能是使用序列化回调(在加载数据之前激发):

第三种选择是通过以下方式将上述内容结合起来:

[ProtoContract(SkipConstructor = true)]
以及:

[ProtoAfterDeserialization]
私人文件
{
如果(Dict==null)Dict=newdictionary();
}

默认为空字典,即使没有数据。注意,您也需要从父级执行此操作,因为它使用默认的子级构造函数;还有其他C#protobuf实现。我提到这一点只是为了解释为什么我把标题改了很多,马克。我尝试了你的建议,他们解决了我的问题。我相信我会选择第三个选项(最少的资源需求)。尤西。
[ProtoContract(SkipConstructor = true)]
[ProtoAfterDeserialization]
private void Foo()
{
    if(Dict == null) Dict = new Dictionary<int,string>();
}