我有两个类,从Treenode派生的“公司”和“文档”。
[Serializable]
[XmlRoot("Company")]
public class Company : TreeNode, IXmlSerializable
{
private string _x;
private string _y;
public Company() { }
[XmlElement("X")]
public string X { get; set; }
[XmlElement("Y")]
public string Y { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Company")
{
x = reader["X"].ToString;
y = reader["Y"].ToString;
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("X", this.X.ToString());
writer.WriteElementString("Y", this.Y.ToString());
}
}
public class Document
{
private int _id;
private string _name;
private Company _company;
public Document() { }
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Company")]
public Company Comp { get; set; }
}
当我尝试序列化文档,然后将其保存到文件中时。但是当我反序列化时,reader参数始终为null。有什么解决方案吗?
这是我的反序列化代码。“ sr”是保存xml文本的变量。
var sr = new StreamReader(ms);
var myStr = sr.ReadToEnd();
XmlSerializer serializer = new XmlSerializer(typeof(List<Document>));
using (TextReader tr = new StringReader(myStr))
{
List<Document> docu = (List<Document>)serializer.Deserialize(tr);
}
我尝试实现ISerialization和调试,但从未执行过,并且尝试覆盖序列化和反序列化方法,但是没有运气。
我正在使用.NET Framework 3.5
如本文所述,IXmlSerializable
正确实施实际上非常棘手。您的实现ReadXml()
似乎违反了使用wrapper元素本身以及所有内容的要求,如下所示:
public void ReadXml(System.Xml.XmlReader reader)
{
reader.MoveToContent();
// Read attributes
Boolean isEmptyElement = reader.IsEmptyElement; // (1)
reader.ReadStartElement();
if (!isEmptyElement) // (1)
{
// Read Child elements X and Y
// Consume the end of the wrapper element
reader.ReadEndElement();
}
}
此外,reader["X"]
返回名为的XML属性的值"X"
,如docs中所述。在您中,WriteXml()
您编写了X
和Y
作为嵌套XML元素的值。这解释了NullReferenceException
。您需要修复您的读写方法,使其保持一致。
但是,我建议您替代实现IXmlSerializable
,即为您的代理引入代理类型Company
。首先,将的所有非属性提取到接口中:TreeNode
Company
public interface ICompany
{
string X { get; set; }
string Y { get; set; }
}
public class Company : TreeNode, ICompany
{
public Company() { }
public string X { get; set; }
public string Y { get; set; }
}
这是可选的,但可使代码更清晰。接下来,介绍一个替代POCO,该POCO实现相同的接口,但不继承自TreeNode
:
public class CompanySurrogate : ICompany
{
public string X { get; set; }
public string Y { get; set; }
public static implicit operator CompanySurrogate(Company company)
{
if (company == null)
return null;
// For more complex types, use AutoMapper
return new CompanySurrogate { X = company.X, Y = company.Y };
}
public static implicit operator Company(CompanySurrogate surrogate)
{
if (surrogate == null)
return null;
// For more complex types, use AutoMapper
return new Company { X = surrogate.X, Y = surrogate.Y };
}
}
请注意,代理可以隐式转换为您的原始Company
类型吗?现在,您可以通过将XmlElementAttribute.Type
属性属性设置为代理的属性来在XML序列化中使用代理:
public class Document
{
public Document() { }
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Company", Type = typeof(CompanySurrogate))]
public Company Comp { get; set; }
}
这样可以避免在执行过程中出错的所有可能性IXmlSerializable
。给定以下输入列表:
var list = new List<Document>
{
new Document { Name = "my name", ID = 101, Comp = new Company { X = "foo", Y = "bar", NodeFont = new System.Drawing.Font("Arial", 10) } },
new Document { Name = "2nd name", ID = 222, Comp = new Company { X = "tlon", Y = "ukbar" } },
};
可以生成以下XML,并可以成功对其进行反序列化:
<ArrayOfDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Document>
<ID>101</ID>
<Name>my name</Name>
<Company>
<X>foo</X>
<Y>bar</Y>
</Company>
</Document>
<Document>
<ID>222</ID>
<Name>2nd name</Name>
<Company>
<X>tlon</X>
<Y>ukbar</Y>
</Company>
</Document>
</ArrayOfDocument>
话虽如此,我真的不推荐这种设计。您的UI应该显示您的数据模型,而不应该是您的数据模型。例如,请参阅如何实现独立于UI的应用程序?。更换Company
用ICompany
尽可能可能是第一步,改变你的设计; 您可能会发现,使用如下所示的替换现有架构变得更加容易TreeNode
:
public class CompanyNode : TreeNode
{
public ICompany Company { get; set; }
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句