4

私は次のXMLを持っています

<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Sites>
  <Site>
    <Code>TWTR</Code>
    <Name>twitter.com</Name>
  </Site>
  <Site>
    <Code>FB</Code>
    <Name>facebook.com</Name>
  </Site>
  <Site>
    <Code>SO</Code>
    <Name>stackoverflow.com</Name>
  </Site>
</Sites>

これはコードです:

public class Program
{
    static void Main(string[] args)
    {
        var fs = new FileStream(@"D:\temp\Sites.xml", FileMode.Open);
        var serializer = new XmlSerializer(typeof(List<Site>));
        var instance = (List<Site>)serializer.Deserialize(fs);
    }
}

[XmlRoot("Sites")]
public class Site
{
    public string Code { get; set; }
    public string Name { get; set; }
}

私が得る例外は次のとおり<Sites xmlns=''> was not expected.です。このエラーの理由は、通常、のXmlRootを定義しない場合ですXmlSerializer。しかし、あなたが見ることができるように、私はクラスSiteをで飾ることによってそれをしましたXmlRootAttribute

私の混乱を完全にするために、次のトリックが機能します。

交換

var serializer = new XmlSerializer(typeof(List<Site>));

var serializer = new XmlSerializer(typeof(List<Site>), new XmlRootAttribute("Sites"));

私は何かが足りないのですか?

4

2 に答える 2

5

XMLを制御できる場合は、以下を変更するだけです。

<Sites> 

<ArrayOfSite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

XMLを制御できない場合は、独自のコレクションを作成し、それに逆シリアル化します。

[XmlRoot("Sites")]
public class Sites : List<Site>
{

}

次のコンストラクターを使用する場合は注意してください。

var serializer = new XmlSerializer(typeof(List<Site>), new XmlRootAttribute("Sites"));

Microsoftがここで指摘しているように、に関連付けられているシリアライザのインス​​タンスをキャッシュしないとList<Site>、メモリリークが発生することになります...

動的に生成されたアセンブリ

パフォーマンスを向上させるために、XMLシリアル化インフラストラクチャは、指定されたタイプをシリアル化および逆シリアル化するアセンブリを動的に生成します。インフラストラクチャは、これらのアセンブリを見つけて再利用します。この動作は、次のコンストラクターを使用している場合にのみ発生します。

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type、String)

他のコンストラクターのいずれかを使用すると、同じアセンブリの複数のバージョンが生成され、アンロードされないため、メモリリークが発生し、パフォーマンスが低下します。最も簡単な解決策は、前述の2つのコンストラクターのいずれかを使用することです。それ以外の場合は、次の例に示すように、アセンブリをハッシュテーブルにキャッシュする必要があります。

于 2013-03-21T10:42:36.453 に答える
4

タイプのオブジェクトを逆シリアル化していないため、XmlRoot追加した属性は使用されません。タイプのオブジェクトを逆シリアル化しているのは、シリアライザーが属性を探す場所です。SiteSiteList<Site>XmlRoot

あなたの回避策は実際には正しい解決策です。ただし、プログラムでこの逆シリアル化を頻繁に実行する場合は、XmlSerializerインスタンスをキャッシュしてください。これは、特定のコンストラクターが動的に生成されたアセンブリを内部的にキャッシュしないためです。これは、通常使用するコンストラクターとは対照的です。

于 2013-03-21T10:16:15.877 に答える