.Net を使用する場合、XmlSerializer の使用にはどのような制限がありますか (ある場合)。

StackOverflow https://stackoverflow.com/questions/109318

  •  01-07-2019
  •  | 
  •  

質問

.Net を使用する場合、XmlSerializer の使用にはどのような制限がありますか (ある場合)。たとえば、画像を XML にシリアル化できますか?

役に立ちましたか?

解決

XmlSerializer にはいくつかの欠点があります。

  1. シリアル化されているすべての型を知っている必要があります。シリアライザーが認識していない型を表すものをインターフェイスで渡すことはできません。
  2. 循環参照はできません。
  3. オブジェクト グラフ内で複数回参照されると、同じオブジェクトが複数回シリアル化されます。
  4. プライベートフィールドのシリアル化を処理できません。

私はこれらの問題のいくつかを回避するために (愚かにも​​) 独自のシリアライザーを作成しました。そんなことはしないでください。これは大変な作業であり、数カ月後には微妙なバグが見つかることになるでしょう。独自のシリアライザとフォーマッタを作成することで得られた唯一のことは、オブジェクト グラフのシリアル化に含まれる詳細をより深く理解できたことです。

私が見つけたのは、 NetDataContractSerializer WCFが出た頃。XmlSerializer が実行しない上記のすべての処理を実行します。これは、XmlSerializer と同様の方法でシリアル化を駆動します。さまざまなプロパティまたはフィールドを属性で修飾して、何をシリアル化するかをシリアライザーに通知します。私が作成したカスタム シリアライザーを NetDataContractSerializer に置き換えたところ、結果に非常に満足しました。ぜひお勧めします。

他のヒント

一般に、XmlSerializer は、単なる DTO 以外の POCO にとっては不適切な選択だと思います。特定の XML が必要な場合は、Xml*Attribute および/または IXmlSerializable のルートに進むことができますが、かなり壊れたオブジェクトが残ります。

目的によっては、たとえ制限があるとしても、これは明らかな選択です。ただし、単純にデータを保存して再ロードする場合は、BinaryFormatter の方が落とし穴が少なく、はるかに簡単な選択であることがわかりました。

ここに、XmlSerializer に関するいくつかの問題点のリストがあります。ほとんどは私が一度は被害を受けたもので、その他は私が見つけたものです。 MSDN:

  • 引数なしのパブリック コンストラクターが必要です
  • パブリックの読み取り/書き込みプロパティとフィールドのみをシリアル化します。
  • すべてのタイプを認識する必要がある
  • 実際には get_* と set_* を呼び出しますので、検証などを行います。実行されます。これは良いことも悪いこともあるかもしれません (呼び出しの順序についても考えてください)
  • 特定のルールに準拠する IEnumerable または ICollection コレクションのみをシリアル化します。

XmlSerializer は、IEnumerable または ICollection を実装するクラスに特別な処理を与えます。IEnumerable を実装するクラスは、単一のパラメーターを取るパブリック Add メソッドを実装する必要があります。Add メソッドのパラメーターは、GetEnumerator から返された値の Current プロパティから返されるものと同じ型、またはその型のベースの 1 つである必要があります。

IEnumerable に加えて ICollection (CollectionBase など) を実装するクラスには、整数を取るパブリック Item インデックス付きプロパティ (C# のインデクサー) が必要であり、整数型のパブリック Count プロパティも必要です。Add メソッドへのパラメーターは、Item プロパティから返されるものと同じ型、またはその型のベースの 1 つである必要があります。ICollection を実装するクラスの場合、シリアル化される値は、GetEnumerator を呼び出すことによってではなく、インデックス付きの Item プロパティから取得されます。

  • IDictionary をシリアル化しない
  • 動的に生成されたアセンブリを使用します。これはアプリ ドメインからアンロードされない可能性があります。

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

xmlserializer.xmlserializer(タイプ)xmlserializer.xmlserializer(タイプ、文字列)

他のコンストラクターを使用すると、同じアセンブリの複数のバージョンが生成され、アンロードされないため、メモリ リークが発生し、パフォーマンスが低下します。

  • ArrayList[] または List<T>[] をシリアル化できません
  • 他にも奇妙なエッジケースがある

次の条件に該当する場合、XmlSerializer をインスタンス化して列挙をシリアル化することはできません。列挙型は unsigned long (C# では ulong) 型で、列挙型には 9,223,372,036,854,775,807 より大きい値を持つメンバーが含まれます。

XmlSerializer クラスは、[Obsolete] としてマークされたオブジェクトをシリアル化しなくなりました。

オブジェクトを逆シリアル化するには、一時ディレクトリ (TEMP 環境変数で定義) に書き込む権限が必要です。

  • エラーに関する有用な情報を取得するには、.InnerException を読み取る必要があります。

もう 1 つの問題は、XmlSerializer のコンストラクターを呼び出すと、実行時にコードがコンパイルされ、逆シリアル化を行うコードを含む一時 DLL (%temp% フォルダー内) が生成されることです。

次の行を app.config に追加すると、コードを確認できます。

  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="4"/>
    </switches>
  </system.diagnostics>

初めてクラスをシリアル化する場合、これには時間がかかり、コンパイルとディスクへの書き込み権限を持つコードが必要になります。

これを回避する方法は、VS 2005+ に付属の sGen.exe ツールを使用してこれらの DLL をプリコンパイルすることです。

詳細については、こちらをご覧ください.

制限があるかどうかはわかりません..しかし、.NET 1.1 の XmlSerialization にはメモリ リークのバグがあり、この問題を回避するにはキャッシュ シリアライザー オブジェクトを作成する必要がありました...実際、この問題が .net 2.0 以降で修正されたかどうかはわかりません...

理論的には、作成したクラスはすべて XmlSerializer を通じてフィードできます。ただし、アクセスできるのはパブリック フィールドのみであり、クラスには正しい属性 (例:Xml属性)。基本的なフレームワークであっても、すべてが XmlSerializer をサポートしているわけではありません。たとえば、System.Collections.Generic.Dictionary<> です。

私が考えられる 1 つの制限は、XmlSerialization がオプトアウトであることです。つまり、シリアル化したくないクラスのプロパティは [XmlIgnore] で修飾されなければなりません。すべてのプロパティがオプトインである DataContractSerializer とは対照的に、包含属性を明示的に宣言する必要があります。ここが良いです 書き上げる.

画像またはそのバイナリ配列は、XmlSerializer によって Base64 エンコードされたテキストとしてシリアル化されます。

たとえば、IDictionary インターフェイスを実装するクラスをシリアル化することはできません。

コレクションの場合は、単一の引数を取る Add メソッドが必要です。特に XML ではなくテキスト形式だけが必要な場合は、JSON を試してみてください。.NET用に開発したのですが、 JsonExSerializer, 、他にも同様に利用可能なものがあります。 http://www.json.org.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top