理解 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
可能应该通过 null
s,因此如果 testDictionary
是 null
,TestDictionary
returns null
;如果 TestDictionary
是 ,将 设置为 null
,则 testDictionary
设置为 null
。
我正在使用 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
可能应该通过 null
s,因此如果 testDictionary
是 null
,TestDictionary
returns null
;如果 TestDictionary
是 ,将 设置为 null
,则 testDictionary
设置为 null
。