8

次のような XML シリアライゼーションを使用することを想像します。

class Foo {
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }

    [XmlInclude]
    public string Name1 { get; private set; }

    [XmlInclude]
    private string Name2;
}

StreamWriter wr = new StreamWriter("path.xml");
new XmlSerializer<Foo>().Serialize (wr, new Foo ("me"));

編集:このコードが間違っていることはわかっています。自分がどのように使いたいかを表示するだけでした。

しかし、これはまったく機能しません:

  • XmlSerializer はジェネリックではありません。(デ) シリアライゼーションのオブジェクトからキャストする必要があります。
  • すべてのプロパティは完全に公開する必要があります。プライベート セッターへのアクセスに Reflection を使用しないのはなぜですか?
  • プライベート フィールドはシリアル化できません。プライベート フィールドを属性で装飾して、XmlSerializer に含めるようにしたいと思います。

XmlSerializer は実際に記述された可能性を提供していますか? これらのケースをより洗練された方法で処理する XML への代替シリアライザーはありますか?

そうでない場合: 結局のところ、現在は 2010 年であり、.NET は何年も前から存在しています。XML シリアライゼーションがよく使用されますが、これは完全に標準であり、非常に簡単に実行できるはずです。それとも、私の理解が間違っている可能性があり、XMLシリアライゼーションは正当な理由で説明されている機能を公開すべきではありませんか?

編集:レガシーは正当な理由ではありません。Listも最初は一般的ではありませんでした。

(キャプションやタグは自由に調整してください。これが CW である必要がある場合は、メモを残してください。)

4

5 に答える 5

12

XmlSerializer クラスを参照してください。使い方が間違っていることがわかります。XmlInclude目的が全く違います。

あなたが正しい。XML シリアライザーは、.NET 1.0 から存在しています。それはジェネリックが登場する前のことなので、ジェネリックをサポートする可能性は低いです。

また、それ以来、より優れたテクノロジーが登場しました。

  • DataContractSerializer は高速で、バイナリとしてのシリアル化をサポートしています
  • LINQ to XML は多くのシリアル化シナリオで使用でき、はるかに柔軟です

XML シリアライザーが将来拡張される可能性は低いです。他の選択肢を学ぶことをお勧めします。

于 2010-03-23T15:52:02.093 に答える
10

最初に固定コード、次に質問への回答:

public class Foo {
    public Foo() : this("") {}
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }
    // note only this will be serialized
    public string Name1 { get; private set; }
    // this won't
    private string Name2;
}

または3.0で:

[DataContract]
class Foo {
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }
    [DataMember]
    public string Name1 { get; private set; }
    [DataMember]
    private string Name2;
}

(およびDataContractSerializerの代わりに使用XmlSerializer)

XmlSerializer はジェネリックではありません。(デ) シリアライゼーションのオブジェクトからキャストする必要があります。

これは、シリアライザーでは一般的です。私は独自のシリアライザーを持っていますが、最初は完全に汎用化しました。そして、それは大きな設計ミスであることが判明しました。巨大。いいえ、真剣に。私は現在、コードのすべての行を書き直して、それを切り替える作業を行っています。

単に; シリアライザーには通常、ある程度のリフレクションが含まれます (実装に応じて、コード生成または実際の作業のいずれか)。リフレクションとジェネリックは、特に WCF などの一部のフレームワークではうまく機能しません。コードに最終的なキャストを実行させることは、公正な妥協です。本当に必要な場合は、これに関するブログエントリがいくつかあります...

すべてのプロパティは完全に公開する必要があります。

これは確かに制限です(setter のないXmlSerializerリスト/コレクションは問題ありませんが、public get と private set がある場合はスローされます)。また、型はパブリックであり、パラメーターなしのコンストラクターを持つ必要があります。

プライベート セッターへのアクセスに Reflection を使用しないのはなぜですか?

パフォーマンスのためにXmlSerializer、アセンブリをオンザフライでビルドして、必要なことを行います。コードの内部に自動的にアクセスすることはできません。参考までに、私は似たようなことをしていますが、2 レベルの生成を提供しています。完全に静的 (デプロイ可能な dll に) であり、パブリック メンバーでのみ動作するか、プライベート メンバーに引き続きアクセスできるメモリ内で動作します。彼らは 1 つのモデルだけに落ち着きたかったのだと思います。

プライベート フィールドはシリアル化できません。プライベート フィールドを属性で装飾して、XmlSerializer に含めるようにしたいと思います。

次にDataContractSerializer、 を使用します。これにより、 とマークされたすべてのメンバー (プライベートを含む) がシリアル化され[DataMember]ます。

于 2010-03-23T16:26:01.530 に答える
7

1: レガシー。XML シリアライザーは、ジェネリックよりも前から存在します。.NET 1.0 と同じです。

2: 設計上の決定。XML シリアライザーは、他のソリューションと比較して、非常に制限された権限で動作するはずです。

3: 2 と同じ。

WCF DataContract シリアライザーを部分的に使用できます。

あなたの仮定は「限られた間違い」です。XMLシリアライゼーションは、私のプロジェクトでは常に別のクラスであり、それ以上何もしない転送ドキュメント用であると思われます。そのため、すべての制限に問題はありません。

于 2010-03-23T15:50:33.103 に答える
1

あなたが持っているように [XmlInclude] は必要ありません。[XmlElement] [XmlAttribute] ... を使用して、クラスがシリアル化される方法を記述できます。

[XmlInclude] を取り出して、それが機能するかどうかを確認します。

class Foo { 
    public Foo (string name) { 
        Name1 = name; 
        Name2 = name; 
    } 

    [XmlAttribute] 
    public string Name1 { get; set; } 

    [XmlAttribute] 
    public string Name2; 
} 

Foo myFoo = new Foo("FirstName", "LastName");
StreamWriter wr = new StreamWriter("path.xml"); 
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
serializer.Serialize(wr,  myFoo);

更新された、シリアル化されたプロパティはパブリックである必要があります。

于 2010-03-23T15:53:13.033 に答える
0

ちなみに、DataContract はバイナリ シリアライゼーションをサポートしていません。xml にシリアライズしますが、バイナリ エンコーディングはサポートしています。

于 2010-03-25T13:37:25.120 に答える