Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# XML序列化彼此内部的元素_C#_.net_Xml_Generics_Serialization - Fatal编程技术网

C# XML序列化彼此内部的元素

C# XML序列化彼此内部的元素,c#,.net,xml,generics,serialization,C#,.net,Xml,Generics,Serialization,我有一个可以自己序列化的类,例如: [XmlRoot("NameOfMyRoot", Namespace = "myNamespace")] public class Inner { public Inner(){} public string SomeString { get; set; } } 这是一个完美的序列化(我正在为myNamespace使用ns别名,请参阅完整演示) 现在我希望此对象成为另一个对象(包装器)的一部分: [XmlRoot(“根”)] 公共舱外 {

我有一个可以自己序列化的类,例如:

[XmlRoot("NameOfMyRoot", Namespace = "myNamespace")]
public class Inner
{
    public Inner(){}
    public string SomeString { get; set; }
}
这是一个完美的序列化(我正在为
myNamespace
使用
ns
别名,请参阅完整演示)


现在我希望此对象成为另一个对象(包装器)的一部分:

[XmlRoot(“根”)]
公共舱外
{
公共T属性{get;set;}
公共外部(){}
公共外部(T内部)
{
属性=内部;
}
}
这就给了我:

<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:ns="myNamespace">
    <Property>
        <ns:SomeString></ns:SomeString>
    </Property>
</Root>

我想要的只是将内部对象按原样嵌入其父对象,如下所示:

<?xml version="1.0" encoding="utf-16"?>
<Root>
    <NameOfMyRoot xmlns:ns="myNamespace">
        <ns:SomeString></ns:SomeString>
    </NameOfMyRoot>
</Root>

请注意,名称空间不应移动到根,并且我不能指定元素的名称,因为将有许多不同的类型。 .

当然,我可以将它们单独序列化,然后通过一些讨厌的字符串操作进行组合,但我希望有一种巧妙的方法来实现这一点。

实现这一点并不容易。不过,您可以在运行时执行此操作:

// perhaps discover these details at runtime
var attribs = new XmlAttributeOverrides();
attribs.Add(typeof(Outer<Inner>), "Property", new XmlAttributes
{
    XmlElements = { new XmlElementAttribute {ElementName = "NameOfMyRoot" } }
});
attribs.Add(typeof(Inner), "SomeString", new XmlAttributes
{
    XmlElements = { new XmlElementAttribute {  Namespace = "myNamespace"} }
});

var ser = new XmlSerializer(typeof(Outer<Inner>), attribs);

var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
ser.Serialize(Console.Out, obj);
如果您不需要这两个
xmlns
别名声明,则可以分别删除它们,但它们不会改变其含义,至少对于兼容的读取器是如此。同样,可以将
ns
添加为别名:

var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ns.Add("ns", "myNamespace");
ser.Serialize(Console.Out, obj, ns);
我在这里所做的是手动编写根节点,只让
XmlSerializer
编写内部内容。请注意,我必须更改SomeString的属性,以使其以您期望的方式工作(其中是具有名称空间的字符串,而不是对象)。

没有简单的方法可以做到这一点。不过,您可以在运行时执行此操作:

// perhaps discover these details at runtime
var attribs = new XmlAttributeOverrides();
attribs.Add(typeof(Outer<Inner>), "Property", new XmlAttributes
{
    XmlElements = { new XmlElementAttribute {ElementName = "NameOfMyRoot" } }
});
attribs.Add(typeof(Inner), "SomeString", new XmlAttributes
{
    XmlElements = { new XmlElementAttribute {  Namespace = "myNamespace"} }
});

var ser = new XmlSerializer(typeof(Outer<Inner>), attribs);

var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
ser.Serialize(Console.Out, obj);
如果您不需要这两个
xmlns
别名声明,则可以分别删除它们,但它们不会改变其含义,至少对于兼容的读取器是如此。同样,可以将
ns
添加为别名:

var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ns.Add("ns", "myNamespace");
ser.Serialize(Console.Out, obj, ns);

我在这里所做的是手动编写根节点,只让
XmlSerializer
编写内部内容。请注意,我必须更改
SomeString
周围的属性,以使其以您期望的方式工作(其中是具有名称空间的字符串,而不是对象)。

注意:问题看起来不一致;
[XmlRoot(“NameOfMyRoot”,Namespace=“myNamespace”)]公共类内部{…}
的xml不是
,而是
——这是一个巨大的问题difference@MarcGravell同意。补充说明:问题看起来不一致;
[XmlRoot(“NameOfMyRoot”,Namespace=“myNamespace”)]公共类内部{…}
的xml不是
,而是
——这是一个巨大的问题difference@MarcGravell同意。我需要在内部类本身上设置名称空间(就像在类的声明中一样)。既不在
SomeString
上,也不在
Root
上。至于元素的名称替换,这很好。@MaximGrishin这是一个名称空间别名声明,而不是名称空间;它在两个级别上都同样有效——别名是继承的,不会更改声明元素的语义。如果您的意思是
NameOfMyRoot
应该在
myNamespace
名称空间中:这不是您的示例所显示的。我很乐意调整我的代码以适应-我编写的代码适合你的例子。@MaximGrishin具体来说,当你说“我想要的只是将内部对象按原样嵌入其父对象,如:
-在该代码中,
NameOfMyRoot
位于空/默认命名空间中,而不是
myNamespace
命名空间。是的,抱歉,我的意思是名称空间别名声明应该属于
NameOfMyRoot
元素。@MaximGrishin不直接支持,但无论名称空间别名声明位于何处,数据的含义都是相同的(或者即使它有别名,也可以使用显式名称空间语法)。我可以问一下为什么需要移动名称空间别名吗?因为它使事情变得非常复杂……我需要在内部类本身上设置名称空间(就像在类的声明中一样)。既不在
SomeString
上,也不在
Root
上。至于元素的名称替换,这很好。@MaximGrishin这是一个名称空间别名声明,而不是名称空间;它在两个级别上都同样有效——别名是继承的,不会更改声明元素的语义。如果您的意思是
NameOfMyRoot
应该在
myNamespace
名称空间中:这不是您的示例所显示的。我很乐意调整我的代码以适应-我编写的代码适合你的例子。@MaximGrishin具体来说,当你说“我想要的只是将内部对象按原样嵌入其父对象,如:
-在该代码中,
NameOfMyRoot
位于空/默认命名空间中,而不是
myNamespace
命名空间。是的,抱歉,我的意思是名称空间别名声明应该属于
NameOfMyRoot
元素。@MaximGrishin不直接支持,但无论名称空间别名声明位于何处,数据的含义都是相同的(或者即使它有别名,也可以使用显式名称空间语法)。我可以问一下为什么需要移动名称空间别名吗?因为这会使事情变得复杂。。。
var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ns.Add("ns", "myNamespace");
ser.Serialize(Console.Out, obj, ns);
<Root xmlns:ns="myNamespace">
  <NameOfMyRoot>
    <ns:SomeString>abc</ns:SomeString>
  </NameOfMyRoot>
</Root>
using System;
using System.Xml;
using System.Xml.Serialization;

[XmlRoot("NameOfMyRoot")]
public class Inner
{
    public Inner() { }
    [XmlElement(Namespace = "myNamespace")]
    public string SomeString { get; set; }
}
static class Program
{
    static void Main()
    {
        using (XmlWriter writer = XmlWriter.Create(Console.Out))
        {
            writer.WriteStartDocument(false);
            writer.WriteStartElement("Root");

            var ser = new XmlSerializer(typeof(Inner));
            var obj = new Inner { SomeString = "abc" };

            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            ns.Add("ns", "myNamespace");
            ser.Serialize(writer, obj, ns);

            writer.WriteEndElement();
            writer.WriteEndDocument();
        }
    }
}