我有一个具有默认值的参考对象,我不希望在序列化时写下这些默认值,这非常有效。
当我在Deserialize期间使用相同的逻辑时,我收到错误。我的目标是避免编写和读取默认值。
以下是有效的示例代码。
this.parenttext = m_rp.parenttext;
//this.parenttext = "Default Value for Parent";
this.childtext = m_rp.Child[m_count].childtext;
//this.childtext = "Default Value for Child";
以下是不起作用的示例代码。
//this.parenttext = m_rp.parenttext;
this.parenttext = "Default Value for Parent";
//this.childtext = m_rp.Child[m_count].childtext;
this.childtext = "Default Value for Child";
完整代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Runtime.Serialization;
static class Module1
{
public static void Main()
{
ReferenceParent rp = new ReferenceParent();
PublicParent p = new PublicParent(rp);
p.parenttext = "Default Value for Parent";
p.Child[0].childtext = "Default Value for Child0";
p.Child[1].childtext = "Default Value for Child1";
p.parenttext = "Non-default Value for Parent";
p.Child[0].childtext = "Non-default Value for Child0";
p.Child[1].childtext = "Non-default Value for Child1";
string xmlstring = null;
XmlWriterSettings xmlws = new XmlWriterSettings();
using (StringWriter sw = new StringWriter())
{
DataContractSerializer dcs1 = new DataContractSerializer(typeof(PublicParent));
xmlws.Indent = true;
xmlws.OmitXmlDeclaration = true;
using (XmlWriter xwriter = XmlWriter.Create(sw, xmlws))
{
dcs1.WriteObject(xwriter, p);
xwriter.Flush();
xmlstring = sw.ToString();
}
}
xmlstring = "<Parent xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/\">\r\n <Child>\r\n <Child />\r\n <Child />\r\n </Child>\r\n</Parent>";
DataContractSerializer dcs2 = new DataContractSerializer(typeof(PublicParent));
using (StringReader sr = new StringReader(xmlstring))
{
using (XmlReader xreader = XmlReader.Create(sr))
{
p = (PublicParent)dcs2.ReadObject(xreader);
}
}
}
[DataContract(Name = "Parent")]
private class PublicParent
{
ReferenceParent m_rp;
[DataMember(EmitDefaultValue = false)]
private string m_parenttext;
public string parenttext;
[DataMember()]
public PublicChild[] Child = new PublicChild[2];
[OnSerializing()]
private void OnSerializing(StreamingContext context)
{
if (this.parenttext == m_rp.parenttext)
//if (this.parenttext == "Default Value for Parent")
{
this.m_parenttext = null;
}
else
{
this.m_parenttext = this.parenttext;
}
}
[OnDeserialized()]
private void OnDeserialized(StreamingContext context)
{
if (string.IsNullOrWhiteSpace(this.m_parenttext))
{
this.parenttext = m_rp.parenttext;
//this.parenttext = "Default Value for Parent";
}
else
{
this.parenttext = this.m_parenttext;
}
}
public PublicParent(ReferenceParent rp)
{
m_rp = rp;
int count;
for (count = 0; count <= 1; count++)
{
Child[count] = new PublicChild(rp, count);
}
}
[DataContract(Name = "Child")]
public class PublicChild
{
ReferenceParent m_rp;
int m_count;
[DataMember(EmitDefaultValue = false)]
private string m_childtext;
public string childtext;
[OnSerializing()]
private void OnSerializing(StreamingContext context)
{
if (this.childtext == m_rp.Child[m_count].childtext)
//if (this.childtext == "Default Value for Child")
{
this.m_childtext = null;
}
else
{
this.m_childtext = this.childtext;
}
}
[OnDeserialized()]
private void OnDeserialized(StreamingContext context)
{
if (string.IsNullOrWhiteSpace(this.m_childtext))
{
this.childtext = m_rp.Child[m_count].childtext;
//this.childtext = "Default Value for Child";
}
else
{
this.childtext = this.m_childtext;
}
}
public PublicChild(ReferenceParent rp, int count)
{
m_rp = rp;
m_count = count;
}
}
}
[DataContract()]
private class ReferenceParent
{
public string parenttext;
[DataMember()]
public ReferenceChild[] Child = new ReferenceChild[2];
public ReferenceParent()
{
parenttext = "Default Value for Parent";
int count;
for (count = 0; count <= 1; count++)
{
Child[count] = new ReferenceChild();
Child[count].childtext = "Default Value for Child" + count.ToString();
}
}
[DataContract()]
public class ReferenceChild
{
public string childtext;
}
}
}
答案 0 :(得分:0)
从快速发布的代码中,跳出来的是你运行反序列化的示例xml代码字符串与序列化的xml字符串的格式不匹配。
序列化实例的输出结果为:
<Parent xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MyTypeNamespace">
<Child>
<Child />
<Child />
</Child>
</Parent>
(其中MyTypeNamesapce是该类型的c#名称空间)
而您正在运行反序列化的xml片段是
<Parent xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/">
<Child>
<Child />
<Child />
</Child>
</Parent>
请注意默认命名空间的差异。默认情况下,DataContractSerializer会将类型的名称空间附加到http://schemas.datacontract.org/2004/07/
的默认名称。
可能这只是你发布代码片段的神器。 名称是否一致,你也可以发布例外吗?
[编辑 - 回应OP的评论]
注释掉你建议的行后,我也得到一个NullReferenceException。
这里的问题是PublicChild.m_rp字段在反序列化时为null。
在创建序列化实例时,可以使用PublicChild(ReferenceParent rp, int count)
构造函数中的PublicParent(ReferenceParent rp)
构造函数。
在反序列化时,这些构造函数不会被调用,因此该字段将为null。你需要以某种方式迎合它;可能是通过在OnDeserialized
。