XmlSerialisation:将一个 属性 序列化为另一个 属性 的属性
XmlSerialisation: Serialize a Property as Attribute of another Property
问题
给定一个可序列化的 Class,其中有很多要序列化的属性,我希望它们中的一些成为另一个属性的属性。
示例
像这样序列化一个Class
[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 我可以通过创建一些(可能是通用的)类 来实现这一点。这会产生很多额外的代码,特别是因为序列化结构中没有可识别的顺序(这是一个定义的标准)。意味着使其通用化会使它比上面添加的更复杂 link - 这就是为什么我想避免这种情况以及我来这里的原因。
所以总的来说,我正在寻找使用属性的解决方案。但我也对其他可能的解决方案持开放态度。
编辑:
澄清一下,我已经知道创建 类 来解决这个问题的可能性。我提出这个问题是因为我想避免这种情况,但我不知道如何避免。
你可以和其他人一起做 class:
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"
另一个解决方案(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();
}
}
问题
给定一个可序列化的 Class,其中有很多要序列化的属性,我希望它们中的一些成为另一个属性的属性。
示例
像这样序列化一个Class
[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 我可以通过创建一些(可能是通用的)类 来实现这一点。这会产生很多额外的代码,特别是因为序列化结构中没有可识别的顺序(这是一个定义的标准)。意味着使其通用化会使它比上面添加的更复杂 link - 这就是为什么我想避免这种情况以及我来这里的原因。
所以总的来说,我正在寻找使用属性的解决方案。但我也对其他可能的解决方案持开放态度。
编辑:
澄清一下,我已经知道创建 类 来解决这个问题的可能性。我提出这个问题是因为我想避免这种情况,但我不知道如何避免。
你可以和其他人一起做 class:
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"
另一个解决方案(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();
}
}