序列化到XML时重命名类 [英] Rename class when serializing to XML
问题描述
我试图序列如下所示的外
类,并从序列化的XML创建一个的XElement
。它有一个属性是键入内蒙古
的。我想双方的名称更改内蒙古
(为 Inner_X
)和外
(为 outer_x的
)。
I'm trying to serialize the Outer
class shown below, and create an XElement
from the serialized XML. It has a property which is of type Inner
. I'd like to change the name of both Inner
(to Inner_X
) and Outer
(to 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
看起来像这样:
This creates an XElement
which looks like this:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<InnerItem />
</Outer_X>
我想的是:
What I would like is:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Inner_X />
</Outer_X>
我要保留有关如何一类应该与该类改名的信息。我想我可以用 XmlType将
属性做到这一点。然而,这个被忽略,属性名来代替。
I want to keep the information about how a class should be renamed with that class. I thought I could do this with the XmlType
attribute. However, this is ignored and the property name is used instead.
I've looked here and here, amongst other places, and feel like this should work. What am I missing?
澄清
通过的保持( ING)有关如何一类应该与该类的改名的信息,我的意思是,这个词 Inner_X
应该只出现在内蒙古
类。它不应该在所有出现在外
类。
By "keep(ing) the information about how a class should be renamed with that class", what I mean is that the term Inner_X
should only appear in the Inner
class. It should not appear at all in the Outer
class.
推荐答案
当的XmlSerializer
连载一类,本身控制其属性创建的元素的名称类型。即属性名称将成为该元素的名称,除非的 XmlElementAttribute.ElementName
。 XmlTypeAttribute.TypeName
一般只控制它所应用类型的实例时,元素名称的不的正在连载一些包含类型的属性 - 例如,当它是根元素,或者当包含在正在与外容器元素序列化集中。此设计避免名称冲突在存在给定类型中的相同类型的多个属性的情况。
When XmlSerializer
serializes a type, the type itself controls the names of the elements created for its properties. I.e. the property name becomes the element name, unless overridden statically by XmlElementAttribute.ElementName
. XmlTypeAttribute.TypeName
generally only controls the element name when an instance of the type to which it is applied is not being serialized as the property of some containing type -- for instance, when it is the root element, or when it is contained in a collection that is being serialized with an outer container element. This design avoids name collisions in cases where there are multiple properties of the same type within a given type.
然而,在多态属性类型的情况下的异常。对于这些,的XmlSerializer
有使用每个可能的多态类型的元素名称的XML类型名称,从而确定从哪个元素创建实际的C#类型选项。要启用此功能,必须添加多个 [XmlElement的(typeof运算(TDerived))]
属性的财产,每个可能的类型 TDerived
。
However, there is an exception in the case of polymorphic property types. For these, XmlSerializer
has an option to use the XML type name of each of the possible polymorphic types as the element name, thereby identifying the actual c# type from which the element was created. To enable this functionality, one must add multiple [XmlElement(typeof(TDerived))]
attributes to the property, one for each possible type TDerived
.
您可以使用此功能来生成您需要通过引入伪多态性代理属性的XML:
You can use this capability to generate the XML you require by introducing a psuedo-polymorphic proxy property:
[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;
}
}
}
则输出为你要求:
Then the output is as you require:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Inner_X />
</Outer_X>
原型的小提琴。
不过,由于@evk评论说,如果你的外
类包含多个属性。同一类型的,这个不能做
However, as @evk commented, if your Outer
class contains multiple properties of the same type, this cannot be done.
另外一个选项来想一想:如果你只是不想手动复制Inner_X
键入多个地点名字符串(即同时在 [XmlType将(字符串名称)]
和 [XmlElement的(串名)]
属性),你可以通过使他们成为公共常量
集中的类型名称:
One other option to think about: if you simply don't want to manually duplicate the "Inner_X"
type name strings in multiple locations (i.e. in both the [XmlType(string name)]
and [XmlElement(string name)]
attributes) you could centralize the type names by making them be 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";
}
更新
我只注意到你的评论我打算内蒙古是一个抽象基类,其中每个子类序列化到不同的元素名称。如果是这种情况,然后 XmlSerializer的
确实可以制成使用XML类型名称作为元素名 - 但只有当它可以静态的属性类型是确定其实多态的因的多存在的 [XmlElement的(typeof运算(TDerived))]
属性。因此,下面的类会为你生成所需的XML:
I just noticed your comment I intend Inner to be an abstract base class, each subclass of which will serialize to different element names. If this is the case, then XmlSerializer
can indeed be made to use the XML type name as the element name -- but only when it can determine statically that the property type is actually polymorphic due to the presence of multiple [XmlElement(typeof(TDerived))]
attributes. Thus the following classes will generate the XML you require:
[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
{
}
这篇关于序列化到XML时重命名类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!