[英]Rename class when serializing to XML
我正在嘗試序列化如下所示的Outer
類,並從序列化的XML創建一個XElement
。 它具有Inner
類型的屬性。 我想將Inner
(更改為Inner_X
)和Outer
(更改為Outer_X
)的名稱。
class Program
{
static void Main(string[] args)
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (TextWriter streamWriter = new StreamWriter(memoryStream))
{
var xmlSerializer = new XmlSerializer(typeof(Outer));
xmlSerializer.Serialize(streamWriter, new Outer());
XElement result = XElement.Parse(Encoding.ASCII.GetString(memoryStream.ToArray()));
}
}
}
}
[XmlType("Outer_X")]
public class Outer
{
public Outer()
{
this.InnerItem = new Inner();
}
public Inner InnerItem { get; set; }
}
[XmlType("Inner_X")]
public class Inner
{
}
這將創建一個如下所示的XElement
:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<InnerItem />
</Outer_X>
我想要的是:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Inner_X />
</Outer_X>
我想保留有關如何使用該類重命名該類的信息。 我以為可以用XmlType
屬性來做到這一點。 但是,將忽略此屬性,而是使用屬性名稱。
我看過這里和這里 ,以及其他地方,覺得這應該可行。 我想念什么?
澄清度
通過“保留有關如何使用該類重命名該類的信息” ,我的意思是,術語Inner_X
僅應出現在Inner
類中。 它根本不應出現在“ Outer
類中。
您需要設置屬性的元素名稱,而不是內部類的xml類型。 嘗試這個:
[XmlType("Outer_X")]
public class Outer
{
public Outer()
{
this.InnerItem = new Inner();
}
[XmlElement("Inner_X")]
public Inner InnerItem { get; set; }
}
public class Inner
{
}
當XmlSerializer
序列化一個類型時,該類型本身將控制為其屬性創建的元素的名稱。 即,屬性名稱將成為元素名稱,除非被XmlElementAttribute.ElementName
靜態覆蓋。 XmlTypeAttribute.TypeName
通常僅在以下情況下才控制元素名稱:當將其應用的類型的實例未序列化為某些包含類型的屬性時,例如,當它是根元素或包含在使用外部容器元素序列化的collection。 在給定類型中存在相同類型的多個屬性的情況下,這種設計可以避免名稱沖突。
但是,多態屬性類型存在例外。 對於這些, XmlSerializer
可以選擇使用每種可能的多態類型的XML類型名稱作為元素名稱,從而標識從中創建元素的實際c#類型。 要啟用此功能,必須[XmlElement(typeof(TDerived))]
屬性添加多個[XmlElement(typeof(TDerived))]
屬性,每種可能的類型TDerived
。
您可以通過引入偽多態代理屬性來使用此功能來生成所需的XML:
[XmlType("Outer_X")]
public class Outer
{
public Outer()
{
this.InnerItem = new Inner();
}
[XmlIgnore]
public Inner InnerItem { get; set; }
[XmlElement(typeof(Inner))]
[XmlElement(typeof(object))]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
public object InnerItemXmlProxy
{
get
{
return InnerItem;
}
set
{
InnerItem = (Inner)value;
}
}
}
然后輸出就如您所願:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Inner_X />
</Outer_X>
原型擺弄 。
但是,正如@evk所說,如果您的Outer
類包含多個相同類型的屬性,則無法完成此操作。
您需要考慮的另一種選擇:如果您只是不想在多個位置手動復制"Inner_X"
類型名稱字符串(即[XmlType(string name)]
和[XmlElement(string name)]
屬性),可以通過將類型名稱設為public const
來集中它們:
[XmlType(Outer.XmlTypeName)]
public class Outer
{
public const string XmlTypeName = "Outer_X";
public Outer()
{
this.InnerItem = new Inner();
}
[XmlElement(Inner.XmlTypeName)]
public Inner InnerItem { get; set; }
}
[XmlType(Inner.XmlTypeName)]
public class Inner
{
public const string XmlTypeName = "Inner_X";
}
更新資料
我剛剛注意到您的評論, 我打算將Inner用作抽象基類,該基類的每個子類將序列化為不同的元素名稱 。 如果是這種情況,則可以確實使XmlSerializer
使用XML類型名稱作為元素名稱-但僅當它可以靜態確定屬性類型實際上是多態的(由於存在多個 [XmlElement(typeof(TDerived))]
屬性。 因此,以下類將生成您需要的XML:
[XmlType("Outer_X")]
public class Outer
{
public Outer()
{
this.InnerItem = new InnerX();
}
[XmlElement(typeof(InnerX))]
[XmlElement(typeof(Inner))] // Necessary to inform the serializer of polymorphism even though Inner is abstract.
public Inner InnerItem { get; set; }
}
public abstract class Inner
{
}
[XmlType("Inner_X")]
public class InnerX : Inner
{
}
這是非常容易實現的。 您需要使用XmlRootAttribute
的class
和XmlElementAttribute
的成員解釋這里在MSDN上 。
[XmlRoot(ElementName = "Outer_X")]
public class Outer
{
[XmlElement(ElementName = "Inner_X")]
public Inner InnerItem { get; set; } = new Inner();
}
public class Inner { }
我創建了一個工作的.NET Fiddle來舉例說明。 這樣的問題解答似乎解決了類似的問題。 最后,在將XML解碼為字符串時,您可能應該使用其他編碼,對嗎? 根據此 ,字符串是UTF-16編碼-不是什么大問題,但想我會呼吁關注它。
我共享的小提琴使用以下XML:
<Outer_X xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Inner_X />
</Outer_X>
更新資料
在澄清您的問題后,現在我明白了您的要求。 不幸的是,(據我所知)無法通過屬性來控制它。 您必須創建自己的XML序列化器/反序列化器,或者接受屬性支持存在限制的事實。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.