理解 Protobuf-net 属性的序列化和反序列化

Understanding Protobuf-net serialization and deserialization of properties

我正在使用 Protobuf-net 序列化程序进行一些测试,并且正在试验属性的序列化。基本上我想将字典(string,int)存储为字典(string,string),然后在反序列化时将(string,string)转换回(string,int)。然而,令我惊讶的是,它在反序列化时通过了 TestDictionary 上的 getter(然后抛出了空引用异常),这让我很困惑。我认为它会通过 setter 反序列化。所以,基本上我不确定 属性 序列化应该如何运作。我写的简单测试class如下:

[ProtoContract]
public class Class1
{
    [ProtoMember(2)]
    public int test;
    public Dictionary<string, int> testDictionary;
    //public Dictionary<string, string> testDictionaryString;
    [ProtoMember(3)]
    private string test2;
    [ProtoMember(4)]
    private string test3;
    [ProtoMember(5)]
    private string test4;

    public Class1()
        {}

    public Class1(int test)
    {
        this.test = test;
            this.testDictionary = new Dictionary<string, int>();
        for (int i = 0; i < test; i++)
        {
            this.testDictionary.Add("a" + i.ToString(), i);
        }
        test2 = (test + 1).ToString();
        test3 = (test + 2).ToString();
        test4 = (test + 3).ToString();
    }

    [ProtoMember(1)]
    public Dictionary<string, string> TestDictionary
    {
        get
        {
            Dictionary<string, string> temp = new Dictionary<string, string>();
            foreach (KeyValuePair<string, int> pair in this.testDictionary)
            {
                temp.Add(pair.Key, pair.Value.ToString());
            }
            return temp;
        }
        set
        {
            testDictionary = new Dictionary<string, int>();
            foreach (KeyValuePair<string, string> pair in value)
            {
                testDictionary.Add(pair.Key, Convert.ToInt32(pair.Value));
            }
        }
    }

出于序列化的目的,字典被视为列表。 您可以想象 默认列表序列化为类似的东西(假设有 set 可用):

var list = obj.TheProperty;
if(list == null) {
    list = new TheListType();
    obj.TheProperty = list;
}
do {
    list.Add(DeserializeTheItemType(reader));
} while ({still that field})

但是,你可以影响它。只需添加 OverwriteTrue = true 就可以满足您的需求:

[ProtoMember(1, OverwriteList = true)]
public Dictionary<string, string> TestDictionary {...}

这现在应该做的更像是:

var list = new TheListType();
do {
    list.Add(DeserializeTheItemType(reader));
} while ({still that field})
obj.TheProperty = list;

然而,这里的一个重要后果是 Merge 将不再以通常的预期方式工作。

附带说明:您的 get/set 可能应该通过 nulls,因此如果 testDictionarynullTestDictionary returns null;如果 TestDictionary,将 设置为 null,则 testDictionary 设置为 null