21

web methodの場合、サードパーティのC#エンティティクラスのオブジェクトを取得します。エンティティクラスはに他なりませんDataContract。このエンティティクラスは非常に複雑で、さまざまなタイプのプロパティがあります。一部のプロパティもコレクションです。もちろん、これらのリンクされたタイプはDataContractsでもあります。

Webサービスのビジネスロジックの一部として、そのDataContractエンティティをXMLにシリアル化したい。XMLスキーマがまったく異なるという理由だけで、(Webメソッドで受け取ったオブジェクトで)直接使用することはできません。DataContractSerializer したがって、DataContractSerializerによって生成されたXMLは、スキーマに対して検証されません。

実装のために従うべきアプローチを結論付けることはできません。次の実装アプローチを考えることができます。

  1. LINQ to XML-これは問題ないように見えますが、オブジェクトのタイプごとに手動でXMLツリー(つまり、クラスインスタンスの要素またはXML表現)を作成する必要があります。多くのエンティティクラスがあり、それらは相互にリンクされているため、XML要素を手動で作成するには手間がかかりすぎると思います。さらに、エンティティクラスが新しいプロパティを導入するときに、XMLツリーを変更し続ける必要があります。これだけでなく、私がXMLツリーを生成するコードは(少なくとも見た目は)少し不器用に見え、将来、他の開発者が保守/変更するのが難しくなります。彼/彼女は、そのXMLがどのように生成されるかを理解するために、それを非常に綿密に調べる必要があります。

  2. XmlSerializer-必要なXML構造を表す独自のエンティティクラスを作成できます。次に、着信オブジェクトから自分のクラスのオブジェクトに詳細をコピーする必要があります。したがって、これは追加の作業です(コードが実行されるときの.NETの場合も同様です!)。次にXmlSerializer、オブジェクトでXMLを生成するために使用できます。この場合、エンティティクラスを作成する必要があり、サードパーティエンティティが変更されるたびに、クラスに新しいプロパティを追加するだけで済みます。(XmlElementまたはXmlAttibute属性を使用)。しかし、人々はDataContractSerializerこれよりも推奨しているので、すべての側面が私に明確でない限り、これを完成させたくありません。

  3. DataContractSerializer-ここでも、サードパーティのDataContractsを制御できないため、独自のエンティティクラスを作成する必要があります。そして、着信オブジェクトから自分のクラスのオブジェクトに詳細をコピーする必要があります。したがって、これは追加の作業です。ただし、DataContractSerializerはXml属性をサポートしていないため、IXmlSerializable必要なXmlをWriteXmlメソッドで実装および生成する必要があります。DataContractSerializerはXmlSerializerよりも高速ですが、サードパーティのエンティティが変更された場合は、(WriteXmlで)変更を処理する必要があります。

質問:

  • パフォーマンスも考慮して、このシナリオで最適なアプローチはどれですか?
  • より良いアプローチを提案できますか?
  • 着信エンティティクラスが変更される可能性がある場合DataContractSerializerは、(パフォーマンスが優れているため)検討する価値がありますか?XmlSerilaizer
  • LINQは本当にシリアル化に使用する必要がありますか?それとも、クエリ以外のことには本当に良いのでしょうか?
  • このような場合、XmlSerializerをLINQよりも優先できますか?はいの場合、なぜですか?
4

3 に答える 3

9

@WernerStrydomの答えに同意します。

XmlSerializerコードが保守可能になり、期待するパフォーマンスが得られるため、使用することにしました。最も重要なのは、XML構造を完全に制御できることです。

これが私の問題を解決した方法です:

要件に従ってエンティティクラス(さまざまなタイプのXml要素を表す)を作成し、XmlSerializerを介してルートクラス(ルート要素を表すクラス)のインスタンスを渡しました。

LINQ1:Mの関係の場合の小さな使用:

特定のノード(say)の下で同じ要素(say Employee)が何度も必要な場合は常にDepartment、タイプのプロパティを宣言しましたList<T>。例えばクラスpublic List<Employee> Employeesで。Departmentこのような場合、XmlSerializerは明らかにノードの下Employeesに(すべての要素のグループ化である)という要素を追加しました。そのような場合、私は(XmlSerializerが.NETオブジェクトをシリアル化した後)XmlSerializerによって生成された(つまりXML)を操作するために使用しました。を使用して、すべてのノードをノードのすぐ下に配置し、ノードを削除しました。EmployeeDepartmentLINQXElementLINQEmployeeDepartmentEmployees

ただし、との組み合わせで期待通りの性能が得られましxmlSerializerLINQ

欠点は、私が作成したすべてのクラスは、内部にある可能性があるときに公開する必要があったことです。

なぜDataContractSerializerですかLINQ-to-XML

  • DataContractSerializerXml属性の使用を許可しません(実装しない限りIXmlSerializable)。DataContractSerializerでサポートされているタイプを参照してください。
  • LINQ-to-XML(そしてIXmlSerializable)複雑なXML構造を作成している間、コードは不器用になり、そのコードは間違いなく他の開発者がそれを維持/変更している間に頭を悩ませるでしょう。

他に方法はありますか?

  • はい。@Werner Strydomが述べたように、Xsd2Codeのようなツールを使用してクラスを生成XSD.exe、結果のクラスに満足している場合はそれらを直接操作できます。
于 2012-07-06T04:34:14.340 に答える
7

XmlSerializerを選択するのは、カスタムスキーマで最も保守しやすいためです(XSDがあると仮定します)。システムの開発が完了したら、システム全体のパフォーマンスをテストし、XMLシリアル化が問題を引き起こしているかどうかを判断します。そうである場合は、さらに作業が必要なものと交換し、もう一度テストして、利益があるかどうかを確認できます。ただし、XMLのシリアル化が問題にならない場合は、保守可能なコードがあります。

XMLデータの小さなスニペットを解析するのにかかる時間は、データベースまたは外部システムとの通信と比較して無視できる場合があります。大容量メモリ(16GB以上)を備えたシステムでは、特に非常に大規模なデータセットとストリームを使用する場合、GCが.NET 4以前のボトルネックになることがあります(.NET 4.5はこれを解決しようとします)。

AutoMapperを使用して、 XSD.EXEによって作成されたオブジェクトをエンティティにマップします。これにより、Webサービスに影響を与えることなくデータベースの設計を変更できます。

LINQ to XMLの優れている点の1つは、XSD検証です。ただし、これはパフォーマンスに影響します。

于 2012-06-22T08:37:58.113 に答える
1

もう1つのオプションは、LINQとReflectionを利用して、オブジェクトをXMLにシリアル化するためのジェネリッククラスを作成することです。この良い例は、http://primecoder.blogspot.com/2010/09/how-to-serialize-objects-to-xml-using.htmlにあります。一日の終わりにあなたのXMLがどのように見える必要があるかはわかりませんが、それがかなり基本的なものであれば、これでうまくいく可能性があります。エンティティクラスがプロパティを追加/削除/変更するときに変更を加える必要はなく、すべてのオブジェクト(およびユーティリティDLLに格納されている場合は他のプロジェクト)でこれを使用できます。

于 2012-07-03T21:48:50.430 に答える