19

Collection から継承し、いくつかのプロパティを追加する単純なクラスがあります。このクラスを XML にシリアル化する必要がありますが、XMLSerializer は追加のプロパティを無視します。

これは、XMLSerializer が ICollection および IEnumerable オブジェクトに与える特別な処理によるものだと思います。これを回避する最善の方法は何ですか?

サンプルコードは次のとおりです。

using System.Collections.ObjectModel;
using System.IO;
using System.Xml.Serialization;

namespace SerialiseCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            var c = new MyCollection();
            c.Add("Hello");
            c.Add("Goodbye");

            var serializer = new XmlSerializer(typeof(MyCollection));
            using (var writer = new StreamWriter("test.xml"))
                serializer.Serialize(writer, c);
        }
    }

    [XmlRoot("MyCollection")]
    public class MyCollection : Collection<string>
    {
        [XmlAttribute()]
        public string MyAttribute { get; set; }

        public MyCollection()
        {
            this.MyAttribute = "SerializeThis";
        }
    }
}

これにより、次の XML が出力されます (MyCollection 要素に MyAttribute がないことに注意してください)。

<?xml version="1.0" encoding="utf-8"?>
<MyCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <string>Hello</string>
    <string>Goodbye</string>
</MyCollection>

私が欲しいのは

<MyCollection MyAttribute="SerializeThis" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <string>Hello</string>
    <string>Goodbye</string>
</MyCollection>

何か案は?シンプルなほど良い。ありがとう。

4

5 に答える 5

16

コレクションは通常、追加のプロパティを配置するのに適した場所にはなりません。シリアル化中とデータ バインディング中の両方で、項目がコレクションのように見える場合は無視されます (シナリオによっては 、 など) IListIEnumerable

それが私なら、コレクションをカプセル化します-つまり

[Serializable]
public class MyCollectionWrapper {
    [XmlAttribute]
    public string SomeProp {get;set;} // custom props etc
    [XmlAttribute]
    public int SomeOtherProp {get;set;} // custom props etc
    public Collection<string> Items {get;set;} // the items
}

もう 1 つのオプションは実装することですIXmlSerializable(かなりの作業が必要です) が、それでもデータ バインディングなどでは機能しません。基本的に、これは想定される使用法ではありません。

于 2008-12-18T10:43:20.560 に答える
13

カプセル化する場合は、Marc Gravell が示唆するように、この投稿の冒頭で、XML を記述したとおりに表示する方法を説明しています。

http://blogs.msdn.com/youssefm/archive/2009/06/12/customizing-the-xml-for-collections-with-xmlserializer-and-datacontractserializer.aspx

つまり、これの代わりに:

<MyCollection MyAttribute="SerializeThis" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <string>Hello</string>
    <string>Goodbye</string>
  <Items>
</MyCollection>

あなたはこれを持つことができます:

<MyCollection MyAttribute="SerializeThis" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">      
  <string>Hello</string>
  <string>Goodbye</string>
</MyCollection>
于 2010-03-25T19:07:54.793 に答える
3

ニール・ウィテカーが示唆するように、そして彼のリンクが切れた場合に備えて..

文字列を格納する内部コレクションを作成し、XmlElement 属性を適用してコレクション名をマスクします。MyCollection が Collection から継承された場合と同じ xml 出力を生成しますが、親要素の属性もシリアル化します。

[XmlRoot("MyCollection")]
public class MyCollection 
{
    [XmlAttribute()]
    public string MyAttribute { get; set; }

    [XmlElement("string")]
    public Collection<string> unserializedCollectionName { get; set; }

    public MyCollection()
    {
        this.MyAttribute = "SerializeThis";
        this.unserializedCollectionName = new Collection<string>();
        this.unserializedCollectionName.Add("Hello");
        this.unserializedCollectionName.Add("Goodbye");
    }
}
于 2015-02-16T13:39:48.883 に答える
0

やりたいことをやりたいだけの場合もあります。フレームワークはのろわれます。

ここに回答を投稿しました List<T> Not Deserialized のプロパティ

それはOPがやりたかったことをします。

于 2015-01-24T22:45:13.980 に答える
0

Romaroo と同じ問題 (ICollection を実装するクラスの xml シリアル化にプロパティを追加したい) と戦ってきました。コレクション クラスにあるプロパティを公開する方法が見つかりませんでした。XmlAttribute タグを使用して、プロパティをルート ノードの属性として表示することも試みましたが、うまくいきませんでした。ただし、クラスで XmlRoot タグを使用して、「ArrayOf...」から名前を変更することができました。興味がある場合の参考文献は次のとおりです。

于 2008-12-30T14:42:22.357 に答える