2013-02-13 5 views
7

私はXMLにシリアライズしようとしているオブジェクトを持っています。このオブジェクトの中には、ジェネリック型(抽象クラ​​ス)のリストがあります。このリストの各項目は、別のクラスかもしれないが、すべては抽象基本クラスから継承されています。私はリストをシリアル化するとき同じ型名のポリモフィックリストをシリアライズ

public abstract class animal 
{ 
    public string type { get; set; } 
} 
public class cat:animal 
{ 
    public string size { get; set; } 
    public string furColor { get; set; } 
} 
public class fish:animal 
{ 
    public string size { get; set; } 
    public string scaleColor { get; set; } 
} 

、私はそれは次のようになりたい:

<animal type="cat"> 
    <size>medium</size> 
    <furColor>black</furColor> 
</animal> 
<animal type="fish"> 
    <size>small</size> 
    <scaleColor>silver</scaleColor> 
</animal> 

I

[XmlElement("Animal")] 
public List<animal> Animals { get; set; } 

しかし、それはオブジェクトタイプ "cat"を期待していないので、エラーをスローします。 [XmlInclude]タグをベースクラス、派生クラス、またはクラスを含む全体に追加すると、これは役に立ちません。

[XmlElement("Animal", typeof(cat))] 
public List<animal> Animals { get; set; } 

をし、私がいる限り、私は唯一の猫を使用して、それがしたいので、これは、正常に動作します:

私は、単一のクラスのためのtypeof指定を使用することができます。繰り返しますが、ミックスにフィッシュを追加すると、同じエラー(魚を期待しない)で爆発します。私は複数のtypeof演算を追加することができます

属性:

[XmlElement("Animal")] 
[XmlElementAttribute(typeof(cat))] 
[XmlElementAttribute(typeof(fish))] 
public List<animal> Animals { get; set; } 

を、これはコンパイルしますが、要素名を無視し、受け入れられないそれぞれ<cat> </cat><fish> </fish>、などのオブジェクトをシリアル化します。タイプ「アニマル」を使用

[XmlElement("Animal", typeof(cat))] 
[XmlElement("Animal", typeof(fish))] 
public List<animal> Animals { get; set; } 

この1つは、この時間を別の例外をスローし、両方のオブジェクト「猫」と「魚」ということ:私も、複数の[のXmlElement]タグを追加しようとしました

同じ範囲。

誰もがこのことを考える方法はありますか?

UPDATEはもう少し掘り後、私は、基本クラスに名前空間を追加することを示唆しているThis SO postが見つかりました:これをシリアル化

[XmlRoot(Namespace="myNamespace")] 
[XmlInclude(typeof(cat))] 
[XmlInclude(typeof(fish))] 
public abstract class animal 

には、次のものが得られます。

<animal xsi:type="cat" type="cat"> 
    ... 
</animal> 
<animal xsi:type="fish" type="fish"> 
    ... 
</animal> 

XSI: type = "cat"はクラスの名前を参照し、type = "cat"は作成されたtype属性を参照します基底クラス内(上の例を参照)。これはですので、私が必要とするものはに近づいています。私はここで未経験で苦しんでいるかもしれないと恐れていますが、xsi:type属性リストを取り除く方法はありますか?ここで

+0

タイトルを編集しました。 「[質問には「タイトル内に「タグ」を含める必要がありますか」(http://meta.stackexchange.com/questions/19190/)」を参照してください。コンセンサスは「いいえ、そうすべきではありません」です。 –

+0

申し訳ありませんが、私はガイドラインでそのビットを逃しました。ヘッドアップをありがとう。 – JesseF

+0

部分的な解決策が見つかりました。詳細は下部の更新をご覧ください。 – JesseF

答えて

3

お使いのベースクラスにXmlInclude属性を追加すると、このserilazationの問題を解決する必要があり

[Serializable] 
    [XmlInclude(typeof(cat))] 
    [XmlInclude(typeof(fish))] 
    class animals 
    { 
     .... 
    } 

    public class cat:animals 
    { 
     public string size { get; set; } 
     public string furColor { get; set; } 
    } 

    public class fish:animals 
    { 
     public string size { get; set; } 
     public string scaleColor { get; set; } 
    } 

UPDATE

が私の側に動作する簡単な例ですが、あなたは実際に私にtype属性を必要としませんあなたがtypeof()メソッドでそれを取り出すことができるからです。 type属性に別の目的がある場合を除きます。この中

 List<animal> animals = new List<animal>(); 
     cat catofdoom = new cat(); 
     catofdoom.furColor = "brown"; 
     catofdoom.size = "10 pounds"; 
     animals.Add(catofdoom); 

     fish fishofdoom = new fish(); 
     fishofdoom.scaleColor = "blue"; 
     fishofdoom.size = "12 inches"; 
     animals.Add(fishofdoom); 


     try 
     { 
      XmlSerializer xs = new XmlSerializer(typeof(List<animal>)); 
      using (StreamWriter wr = new StreamWriter("animal.xml")) 
      { 
       xs.Serialize(wr, animals); 
      } 
     } 
     catch (Exception e) 
     { 

      throw; 
     } 

結果(オプションなしで非常に基本的なシリアライズ):

<?xml version="1.0" encoding="utf-8"?> 
<ArrayOfAnimal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <animal xsi:type="cat"> 
    <size>10 pounds</size> 
    <furColor>brown</furColor> 
    </animal> 
    <animal xsi:type="fish"> 
    <size>12 inches</size> 
    <scaleColor>blue</scaleColor> 
    </animal> 
</ArrayOfAnimal> 
+0

私はそれを試みましたが、それでも私にエラーが表示されます "タイプcatは期待されていませんでした。静的に知られていないタイプを指定するには、XmlIncludeまたはSoapInclude属性を使用してください。それは上記と全く同じです。私は行方不明の何か他にありますか? – JesseF

+0

私は、.NET 4.5 WebAPIソリューションを使用していることを言及する必要があります。私はLegrandvikingに同意します、上記の解決策はうまくいくはずです。私たちはどちらも間違っているのですか?私は "バグ"の旗を振ることに躊躇しています、誰もがこの作品のようなものを作りましたか? – JesseF

+0

元の回答を更新しました。うまくいけば、これはあなたの必要性に合うでしょう – legrandviking

1

私はDataContractSerializerを使用することをお勧めしてシリアライザに知られているタイプがあります。 XmlIncludeを使用すると、encasulationの原則のための休憩のようなものです。 いくつかのサンプルについては、MSDNのリンクを参照してください...

+0

私はJasterに同意しています。柔軟性があり、守備可能なメンバーを公開する必要はありません。 – legrandviking

+0

ええと...これはオブジェクト全体のリファクタを必要とします。 – JesseF

+0

私の研究が正しければ、属性を使用する必要があるためDataContractSerializerを使用できないため、XMLSerializerが残っています。無関心な属性のいくつかを取り除くことに私を戻します。 – JesseF

1

両方が必要です!

[Serializable] 
[XmlInclude(typeof(cat))] 
[XmlInclude(typeof(fish))] 
class animals 
{ 
    .... 
} 

public class cat:animals 
{ 
    public string size { get; set; } 
    public string furColor { get; set; } 
} 

public class fish:animals 
{ 
    public string size { get; set; } 
    public string scaleColor { get; set; } 
} 

XmlElementの名前が少し変更されています。これで正しく動作します。

[XmlElement("cat", typeof(cat))] 
[XmlElement("fish", typeof(fish))] 
public List<animal> Animals { get; set; } 
+0

これは実際に質問に答えます。 – CSharper

関連する問題