序列化到XML时重命名类 [英] Rename class when serializing to XML

查看:113
本文介绍了序列化到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆