【问题标题】:XmlSerialisation: Serialize a Property as Attribute of another PropertyXmlSerialisation:将一个属性序列化为另一个属性的属性
【发布时间】:2015-05-28 06:55:27
【问题描述】:

问题

给定一个具有许多要序列化的属性的可序列化类,我希望其中一些成为另一个属性。

样本

像这样序列化一个类

[Serializeable]
public class MySerializeableClass {

    public string AnyPath { get; set; }

    public bool IsActive { get; set; }

}

结果是

<MySerializeableClass>
    <AnyPath>C:\</AnyPath>
    <IsActive>true</IsActive>
</MySerializeableClass>

但它应该

<MySerializeableClass>
    <AnyPath IsActive="true">C:\</AnyPath>
</MySerializeableClass>

要求

我已阅读here,我可以通过创建一些(可能是通用的)类来实现这一点。这会产生很多额外的代码,特别是因为序列化结构中没有可识别的顺序(这是一个定义的标准)。意味着使其通用化会使它比上面添加的链接更加复杂 - 这就是我想避免这种情况以及我来到这里的原因。

所以总的来说,我正在寻找使用属性的解决方案。但我也对其他可能的解决方案持开放态度。

编辑:

澄清一下,我已经知道创建类来解决这个问题的可能性。我提出这个问题是因为我想避免这种情况,但我不知道该怎么做。

【问题讨论】:

标签: c# serialization


【解决方案1】:

你可以用其他类来做到这一点:

public class MyPathClass
{
    [XmlAttribute]
    public bool IsActive { get; set; }

    [XmlText]
    public string Value { get; set; }

    public static implicit operator string(MyPathClass value)
    {
        return value.Value;
    }

    public static implicit operator MyPathClass(string value)
    {
        return new MyPathClass { Value = value };
    }
}

public class MySerializeableClass
{
    [XmlElement]
    public MyPathClass AnyPath { get;set; }
}

用法:

MySerializeableClass item = new MySerializeableClass() { AnyPath = "some path" };

XML:

<?xml version="1.0"?>
<MySerializeableClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <AnyPath IsActive="false">some path</AnyPath>
</MySerializeableClass>

获取路径(自动转换为字符串):

string path = item.AnyPath; // path="some path"

【讨论】:

  • 这是一个很酷的想法......还有你如何路由内部价值......关键是我想避免使用单独的类的解决方案。
  • @LuckyLikey 您可以创建一个名为 IsActive 的布尔类型的属性,您只需将其从序列化中排除,并且在该属性中只需 return AnyPath.IsActive
  • @Georg 是的,我知道,但想象一下,如果我对我想要作为属性的每个属性都这样做。它会使我的代码膨胀很多。
  • @LuckyLikey:如果课程数量比你想象的多怎么办?代码行数越少,你的报酬越高吗?
  • @cosmo0 不。但代码因其简单而受到喜爱。
【解决方案2】:

另一种解决方案(IXmlSerializable

public class MySerializeableClass : IXmlSerializable
{
    public bool IsActive { get; set; }

    public string AnyPath { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        reader.Read();
        if (reader.Name == "AnyPath")
        {
            if (reader.HasAttributes)
            {
                this.IsActive = string.Equals(reader.GetAttribute("IsActive"), "true", StringComparison.InvariantCultureIgnoreCase);
            }
            this.AnyPath = reader.ReadElementContentAsString();
            reader.ReadEndElement();
        }
        else
        {
            throw new FormatException();
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteStartElement("AnyPath");
        writer.WriteAttributeString("IsActive", IsActive ? "true" : "false");
        writer.WriteString(AnyPath);
        writer.WriteEndElement();
    }
}

【讨论】:

  • 这很酷。即使我不想要任何特殊行为,我现在是否必须为我的所有属性实现此功能,或者我可以将它们仅归为 [XmlAttribute] 并且 XmlSerializer 仍然会正确执行它们吗?
  • IXmlSerializable 是您自己的序列化实现,因此您必须手动编写所有节点。不存在通用解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 2017-08-20
  • 1970-01-01
  • 2011-05-09
相关资源
最近更新 更多