8

私のリポジトリにはがありList<Student>、登録にはEnrolment.StudentとEnrolment.Courseがあります。これらは、前の2つのリストの学生またはコースの1つを参照しています。 List<Course>List<Enrolment>

リポジトリでXmlSerializerを使用すると、List<Student>の同じ学生への参照ごとに、各学生のすべてのプロパティがシリアル化されるため、冗長データが出力されList<Enrolment>ます。私はこれを解決するためのエレガントな方法を探しています。

デシリアライズ後、デシリアライズによって作成された重複オブジェクトインスタンスのID値を使用して参照を修正できますが、これはハックのようです。

冗長な出力を修正する1つの方法は、XmlIgnore Enrolment.StudentとEnrolment.Courseを使用して、シリアル化用にさらに2つのプロパティ(Enrolment.StudentIDとEnrolment.CourseID)を作成することです。List<Student>ただし、逆シリアル化中は、およびの逆シリアル化の結果が利用できないため、Enrolment.StudentおよびEnrolment.Courseの参照を設定できません(AFAIK)List<Course>

私が考えたもう1つの方法は、オブジェクト階層の下位でシリアル化することです。各リストを個別に実行し、逆シリアル化の順序を制御します。これは実行しません。

もう1つの方法は、XmlIgnoreを使用して、それ自体の逆シリアル化が完了した後にList<Enrolment>初期化する登録シリアル化ヘルパークラスを作成することです。List<Enrolment>これは大変な努力のようです。

他の人は、XmlSerializerを使用して、同じオブジェクトへの複数の参照をどのようにシリアル化/逆シリアル化しますか?

4

5 に答える 5

3

シリアル化の苦痛:->..。

これに対する一般的な解決策はありませんでした。それが、MSがSilverlightフレームワークからそれを取り除いた理由だと思います。

.netフレームワークの自動シリアル化メカニズムに依存することはありません。私自身のモデルとリポジトリの場合、私は通常、どのプロパティが単純なスカラープロパティ(数値/文字列など)であり、どのプロパティが他のオブジェクトへのリンクであるか(およびどちらのリストでもあるか)を知っているか、プログラムで簡単に判断できます。

基本的に2つのシナリオがあります。

1:オブジェクトのフラットな情報のみをシリアル化/転送したい。その場合、他のオブジェクトにリンクしているプロパティのそれぞれのIDのみを転送します。その後、受信者は後続のクエリを実行して、必要な他のすべてのオブジェクトを取得できます。

2:できるだけ多くの情報を転送したい。つまり、いくつかのレベルを持つより深いネストされたXMLを転送したい。主に、XML上のCSSのみを使用してすべてを直接表示するレポート機能のために。その場合、実際には、同じオブジェクトがXMLツリーに複数回解決されることが望まれます。

後続のクエリ呼び出しが多すぎるのを避けるために、最初のシナリオを少し調整する必要がある場合もありますが、通常は非常にうまくいきます。つまり、コードベースに組み込んで、いつ解決する追加のオブジェクトを指定したり、どこかに構成したりすることができます。

于 2010-01-08T11:25:52.493 に答える
2

XMLシリアライザーを使用したこの問題の解決策はありません。重複を削除するために使用する可能性のあるIDの概念はありません。

できる最善の方法は、オブジェクトのプールをそれらの参照とは別にシリアル化することです。その後、逆シリアル化後にリストを再作成できます。

ところで、XmlSerializerはC#に固有のものではないことをご存知ですか?

于 2010-01-08T08:22:10.883 に答える
2

EnrollmentにインターフェイスIXmlSerializableを実装し、WriteXmlメソッドで、キーのみを含む学生およびコースのXMLを生成できます。例:

<Student Id="5"/>
<Course Id="6"/>

ReadXmlメソッドでは、これから参照をロードできます。また、XmlIgnore属性をStudentおよびCourseプロパティに設定する必要があります。

于 2010-01-08T08:32:55.247 に答える
0

How does this sound as a solution:

  1. XMLIgnore each secondary reference ie Enrolment.Student & Enrolment.Course
  2. create a property for each secondary reference that is used to serialize/deserialize a foreign key for that reference instead - Prefix with XML_FK. eg XML_FK_Student & XML_FK_Course
  3. Create a method XML_FinalizeDeserialization that is called after deserialization to load the references using those foreign key properties.
于 2010-01-08T14:30:43.127 に答える
0

datacontractシリアライザーでReferenceTrackingを使用する必要があります/使用できます。

//deserilaize:
using(MemoryStream memStmBack = new MemoryStream()) {
  var serializerForth = new DataContractSerializer(
    typeof(YourType),
    null,
    0x7FFF /*maxItemsInObjectGraph*/ ,
    false /*ignoreExtensionDataObject*/ ,
    true /*preserveObjectReferences*/ ,
    null /*dataContractSurrogate*/ );

  byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
  memStmBack.Write(data, 0, data.Length);
  memStmBack.Position = 0;
  var lsBack = (YourType) serializerForth.ReadObject(memStmBack);

}
//serialize...
using(MemoryStream memStm = new MemoryStream()) {
    var serializer = new DataContractSerializer(
      typeof(YourType),
      knownTypes,
      0x7FFF /*maxItemsInObjectGraph*/ ,
      false /*ignoreExtensionDataObject*/ ,
      true /*preserveObjectReferences*/ ,
      null /*dataContractSurrogate*/ );

    serializer.WriteObject(memStm, yourType);

    memStm.Seek(0, SeekOrigin.Begin);

    using(var streamReader = new StreamReader(memStm)) {
        result = streamReader.ReadToEnd();

または使用する

[Serializable]
[DataContract(IsReference = true)]
于 2018-08-29T09:09:02.237 に答える