如何序列化基本类型集合并在易于阅读的 XML 中查看具体类型

发布于 2024-08-28 21:14:43 字数 625 浏览 4 评论 0原文

我有一个列表,其中填充了各种具体类型的对象,

我正在使用 WCF DataContractSerializer

<Children>
    <BaseType xmlns:d3p1="http://schemas.datacontract.org/2004/07/Tasks"
              i:type="d3p1:ConcreteTypeA"></BaseType>
    <BaseType xmlns:d3p1="http://schemas.datacontract.org/2004/07/Tasks"
              i:type="d3p1:ConcreteTypeB"></BaseType>
</Children>

子类 BaseType有没有办法生成它

<Children>
    <ConcreteTypeA/>
    <ConcreteTypeB/>
</Children>

真正的目标是让用户生成一些 XML 来加载到内存中,而用户的技能水平要求他们提供原始 XML 是不会成功的。

I have a List which is populated with objects of various concrete types which subclass BaseType

I am using the WCF DataContractSerializer

<Children>
    <BaseType xmlns:d3p1="http://schemas.datacontract.org/2004/07/Tasks"
              i:type="d3p1:ConcreteTypeA"></BaseType>
    <BaseType xmlns:d3p1="http://schemas.datacontract.org/2004/07/Tasks"
              i:type="d3p1:ConcreteTypeB"></BaseType>
</Children>

Is there any way to get this to generate

<Children>
    <ConcreteTypeA/>
    <ConcreteTypeB/>
</Children>

?

The real goal is to let users generate some XML to load into memory, and the users are of a skill level that asking them for the original XML is not going to be successful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

因为看清所以看轻 2024-09-04 21:14:43

DataContractSerializer 的设计目的不是为了让您控制输出。它被设计为快速、隐式且易于归属类。

您想要的是 XmlSerializer。这使您可以更好地控制 XML 输出。

请注意,在下面的示例中,我指定了很多可以从属性名称推断出来的内容,但只是为了让您感觉到可以在属性中覆盖它们。事实上,我认为如果删除所有属性并应用一些 KnownTypeAttributes,整个类就会很好地序列化,但我还没有测试它。我不知道这是否会给您所描述的确切 XML(它将在 Children 之上创建一个根元素),但希望这能让您朝着正确的方向前进。

控制 XML 序列化的属性

[XmlRoot(Namespace="")]
public class MyClass {

    [XmlArray("Children")]
    [XmlArrayItem("ConcreteTypeA", typeof(ConcreteTypeA))]
    [XmlArrayItem("ConcreteTypeB", typeof(ConcreteTypeB))]
    public BaseType[] Children {
        get;
        set;
    }

}

public class BaseType {
}

public class ConcreteTypeA : BaseType {
}

public class ConcreteTypeB : BaseType {
}

编辑:I刚刚测试过,它产生的东西非常接近你正在寻找的东西。

void Main()
{

    var mc = new MyClass();
    mc.Children = new BaseType[] {
        new ConcreteTypeA(),
        new ConcreteTypeB(),
        new ConcreteTypeA(),
        new ConcreteTypeB()
    };

    var serializer = new XmlSerializer(typeof(MyClass));

    using ( var str = new StringWriter() ) {
        serializer.Serialize(str, mc);
        str.ToString().Dump();
    }

}

...产生...(从顶部删除无用的 xmlns)

<MyClass>
  <Children>
    <ConcreteTypeA />
    <ConcreteTypeB />
    <ConcreteTypeA />
    <ConcreteTypeB />
  </Children>
</MyClass>

DataContractSerializer is not designed to let you control the output. It's designed to be fast, implicit, and easy to attribute a class with.

What you want is the XmlSerializer. This gives you a lot more control over the XML output.

Note that in my example below I specified a lot of things that could have been inferred from the property names but just to give you the sense that you can override them in the attributes. In fact I think this whole class would serialize just fine if all the attributes were removed and some KnownTypeAttributes were applied but I haven't tested it. I don't know if this will give you the exact XML you described (it will create a root element above Children) but hopefully this sets you in the right direction.

Attributes That Control XML Serialization

[XmlRoot(Namespace="")]
public class MyClass {

    [XmlArray("Children")]
    [XmlArrayItem("ConcreteTypeA", typeof(ConcreteTypeA))]
    [XmlArrayItem("ConcreteTypeB", typeof(ConcreteTypeB))]
    public BaseType[] Children {
        get;
        set;
    }

}

public class BaseType {
}

public class ConcreteTypeA : BaseType {
}

public class ConcreteTypeB : BaseType {
}

EDIT: I just tested and it produces something very close to what you were seeking.

void Main()
{

    var mc = new MyClass();
    mc.Children = new BaseType[] {
        new ConcreteTypeA(),
        new ConcreteTypeB(),
        new ConcreteTypeA(),
        new ConcreteTypeB()
    };

    var serializer = new XmlSerializer(typeof(MyClass));

    using ( var str = new StringWriter() ) {
        serializer.Serialize(str, mc);
        str.ToString().Dump();
    }

}

...produces... (useless xmlns removed from the top)

<MyClass>
  <Children>
    <ConcreteTypeA />
    <ConcreteTypeB />
    <ConcreteTypeA />
    <ConcreteTypeB />
  </Children>
</MyClass>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文