2011-07-13 5 views
3

XMLドキュメントをリスト<にデシリアライズしようとしています。私の目標は、リスト<にXML文書からのデータを返すパブリック静的メソッドがあることです。ここでXMLドキュメントをリスト<>にデシリアライズしてアイテム名をオーバーライドする方法

はXMLである:ここでは

<?xml version="1.0"?> 
<root> 
    <item> 
     <name>Blue</name> 
    </item> 
    <item> 
     <name>Red</name> 
    </item> 
</root> 

は、アイテム(BillingItem.cs)のためのクラスです。ここ

using System; 
using System.Xml.Serialization; 

namespace DeserializeExample 
{ 
    [Serializable] 
    [XmlRoot("item")] 
    public class BillingItem 
    { 
     [XmlElement("name")] 
     public string Description { get; set; } 
    } 
} 

は、リスト(BillingItems.cs)であるクラスです。

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

namespace DeserializeExample 
{ 
    [Serializable] 
    [XmlRoot("root")] 
    public class BillingItems : List<BillingItem> 
    { 
     public static BillingItems GetBillingItems() 
     { 
      using (TextReader reader = new StreamReader("BillingItems.xml")) 
      { 
       XmlSerializer serializer = new XmlSerializer(typeof(BillingItems)); 
       return (BillingItems)serializer.Deserialize(reader); 
      } 
     } 
    } 
} 

そして、ここで私はリスト(Program.csを)を取得できるようにしたいと思います方法の例を使用してコンソールアプリです:

namespace DeserializeExample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      BillingItems billingItems = BillingItems.GetBillingItems(); 
     } 
    } 
} 

コンソールアプリケーションを実行すると、リストは空になります。私はそれがどのように属性を使用しているかに関係していると思いますが、この作業をどのように行うかを決めることはできません。

例がシンプルで、うまく説明され、誰かが助けてくれることを願っています。

答えて

3

私はリストをカプセル化します - 簡単にするために一部に(XmlSerializerコンストラクタをいくつか危ないオーバーロードを回避する)、部分的にはそれが信頼性のない作りCFなどで、ここでいくつかの不具合がありますので。しかし:

public class BillingItem 
{ 
    [XmlElement("name")] 
    public string Description { get; set; } 
} 
[XmlRoot("root")] 
public class MyResult 
{ 
    [XmlElement("item")] 
    public List<BillingItem> Items { get; set; } 
} 

(私はすべての不要な他の属性を削除した)

それからちょうど(明らかに、より適切な名前)MyResultを返し、それはあなたの例のようにシリアライズされます。

+0

ご回答いただきありがとうございます。実際にはうまくいくと考えております。しかし、私はこれを単純なままにしておきたいという私の元の投稿には言及していませんでしたが、私はCSLAフレームワークを利用する既存のアプリケーションに新しい機能を追加しています。このフレームワークでは、物のリストは特別なリスト(BusinessListBase)として実装されています。そこでは、すべての物のリストがそれ自身のリストを返すpublic staticメソッドを持っています。だから私はあなたが提案するカプセル化クラスを使用しないようにする必要があります。 –

+0

@Doug私が言うことは、コアアプリケーションとは異なり、シリアライゼーションの境界で微妙に異なる表現をすることが必要なことです(実際には望ましいことです)。私は単にこれを上記の例として書き留めます(シリアライゼーション層を通過する直前にラップしてください)。それは、少なくとも私がやることです。 –

+0

私は理解していますが、アプリケーション全体がビルドされています。「物事」のリストが必要な場合は、単純にThings.GetThings()を呼び出すと、Thingオブジェクトのリストが返されます。そのコンベンションを破るには、膨大な時間のリファクタリングが必要になります。何かは、この問題に対する簡単な答えがあることを私に伝えます。しかし、これまであなたの助けに感謝します。 –

1

あなたの例では、シリアライゼーションが不要なようです。そうでない場合は、LINQからXMLを使用して解析し検討してください。

using System.Xml.Linq; 

public class BillingItems : List<BillingItem> 
{ 
    // Constructor. 
    private BillingItems(List<BillingItem> items) : base(items) { } 

    public static BillingItems GetBillingItems() 
    { 
     var doc = XDocument.Load("BillingItems.xml"); 
     var items = (from i in doc.Element("root").Elements("item") 
         select new BillingItem { Description = i.Element("name").Value }) 
        .ToList(); 
     return new BillingItems(items); 
    } 
} 

はまた、あなたは/挿入する項目を削除することを計画していない限り> IEnumerableを<>というより一覧<を使用して検討する必要があります。

EDIT:下記のOPのコメントに従って、BillingItemsがList <>を継承するように上記のコードを変更しました。

+0

ありがとう、私はあなたが何をしているか見ることができます。しかし、これは呼び出し側がBillingItemsオブジェクトをインスタンス化して新しいものを取得できることを期待しているため、コンパイルされません(上記のコンソールアプリケーションを参照してください)。エラー「System.Collections.Generic.List 」を「DeserializeExample.BillingItems」に暗黙的に変換できません\t C:\ Users \ doug.ramirez \ Documents \ Visual Studio 2010 \ Projects \ DeserializeExample \ DeserializeExample \ Program.cs DeserializeExample –

+0

こんにちはDoug、あなたのコメントごとに上記のコードスニペットを修正しました。試してみてください。コンストラクタは1つのList <>から別のList <>にすべての項目をコピーする必要がありますが、あなたのニーズを満たすかもしれないので、それは非常に理想的ではありません。 –

+0

ケビン、私は今朝私の解決策を掲載するまであなたの投稿を見ませんでした(下記参照)。あなたのソリューションは完璧に動作します、ありがとう。私は試して、私のアプリであなたのデザインを実装し、それがどうなるか見てみましょう。 –

0

私はXmlSerializerに何かがあると思うので、私はこれが好きではありませんが、これは私にとってはugですが、その間に私は次のことを行うつもりです。

using System.Xml.Serialization; 

namespace DeserializeExample 
{ 
    [XmlRoot("root")] 
    public class BillingItemResult 
    { 
     [XmlElement("item")] 
     public BillingItems Items { get; set; } 
    } 
} 

はその後、私のBillItems.csクラスでプライベート静的ボイド方法は、カプセル化オブジェクトを取得し、それが課金アイテムのリストですが返されます:

私が本当にしたいリストをカプセル化するクラスを追加

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Xml.Linq; 
using System.Xml.Serialization; 

namespace DeserializeExample 
{ 
    [Serializable] 
    [XmlRoot("root")] 
    public class BillingItems : List<BillingItem> 
    { 
     public static BillingItems GetBillingItems() 
     { 
      using (TextReader reader = new StreamReader("BillingItems.xml")) 
      { 
       XmlSerializer serializer = new XmlSerializer(typeof(BillingItemResult)); 
       BillingItemResult billingItemResult = (BillingItemResult)serializer.Deserialize(reader); 
       return billingItemResult.Items; 
      } 
     } 
    } 
} 

これにより、既存のアプリケーションのデザインと規約をそのまま維持できます。ここにCLIからのサンプルがあります:

これは動作しますが、私はまだ、追加のラッピングクラスを必要としないもっとシンプルなものがあると思います。