序列化/反序列化从Treenode派生的XML

布利斯顿

我有两个类,从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()您编写了XY作为嵌套XML元素的值这解释了NullReferenceException您需要修复您的读写方法,使其保持一致。

但是,我建议您替代实现IXmlSerializable,即为代理引入代理类型Company首先,将的所有非属性提取到接口中:TreeNodeCompany

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的应用程序?更换CompanyICompany尽可能可能是第一步,改变你的设计; 您可能会发现,使用如下所示的替换现有架构变得更加容易TreeNode

public class CompanyNode : TreeNode
{
    public ICompany Company { get; set; }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章