我需要复制这种XML格式:
<item>
<attribute1>1</attribute1>
<attribute2 something="true">
2
</attribute2>
<attribute3 something="false">
3
</attribute3>
<!-- goes on until attribute25 -->
</item>
我目前正在使用这样的东西来实现我的目标:
Item.cs:
[XmlType(TypeName = "item")]
public class Item {
[XmlElement("attribute1")]
public CustomElement<string> Attribute1 { get; set; }
[XmlElement("attribute2")]
public CustomElement<string> Attribute2 { get; set; }
[XmlElement("attribute3")]
public CustomElement<string> Attribute3 { get; set; }
// Etc Etc
}
CustomElement.cs:
/// <summary>
/// Represents a CustomElement.
/// </summary>
/// <typeparam name="T">The type for the value of the element.</typeparam>
public class CustomElement<T>
{
[XmlIgnore] public T Value;
[XmlText]
public T XmlValue => Value;
public CustomElement()
{
}
public CustomElement(T value)
{
Value = value;
}
[XmlIgnore]
public bool? Something { get; set; }
[XmlAttribute("something")]
public bool XmlSomething
{
get => Something != null && Something.Value;
set => Something = value;
}
public bool XmlSomethingSpecified => Something.HasValue;
public static implicit operator CustomElement<T>(T x)
{
return new CustomElement<T>(x);
}
}
然而,在序列化我的Item
后,我得到了:
<item>
<attribute1 />
<attribute2 />
<attribute3 />
</item>
如何修复我的CustomElement
课程以使价值不会丢失?
答案 0 :(得分:3)
这里有几个问题:
您正在尝试序列化XmlValue
成员作为为CustomElement<T>
实例生成的元素的元素值,但您已将其定义为只读< / strong> expression-bodied member:
public T XmlValue => Value;
XmlSerializer
只会序列化公共读/写属性和字段,因此您必须添加setter和getter:
[XmlText]
public T XmlValue { get => Value; set => Value = value; }
或者,为了简化您的模型,您可以完全删除XmlValue
并直接序列化Value
,并使用[XmlText]
进行标记。 XML序列化属性可以应用于字段和属性。
您正尝试使用{propertyName}Specified
pattern在基础值为<something>
时禁止null
元素的序列化。此模式主要用于跟踪,无论是否遇到关联元素,因此xxxSpecified
属性必须标有[XmlIgnore]
:
[XmlIgnore]
public bool XmlSomethingSpecified => Something.HasValue;
或者,由于您实际上并不需要跟踪<something>
元素的存在,因此您可以通过切换到ShouldSerialize{PropertyName}()
模式来简化模型:
public bool ShouldSerializeXmlSomething() => Something.HasValue;
ShouldSerialize() vs Specified Conditional Serialization Pattern。
如果您的Item
类型将成为XML文档的根元素,则必须使用[XmlRoot("item")]
对其进行标记,以使根元素的名称为{{1 }}:
<item>
在您的c#代码中,您已将[XmlRoot("item")]
[XmlType(TypeName = "ci")]
public class Item
{
// Etc Etc
}
属性标记为XmlSomething
,但在您的XML [XmlElement]
中显示为元素:{{ 1}}。
如果您确实希望它成为元素,则必须使用something
标记<something>true</something>
:
XmlSomething
在您的问题中,您展示了一个带有非布尔文本值的[XmlElement]
元素的示例:
[XmlElement("something")]
public bool XmlSomething
{
get => Something != null && Something.Value;
set => Something = value;
}
我认为这是问题中的拼写错误,但如果没有,则需要重新设计<something>
类型,以使<attribute3>
3
<something>text</something>
</attribute3>
成为CustomElement<T>
。
示例工作Roslyn .Net fiddle,second包含Something
的建议简化,third string
显示为子元素。
第二小提琴的类看起来像:
CustomElement<T>