1

これが私の古いクラス図です(簡略化)。

public class Main
    Public Property ListOfA As ClassACollection
End Class

Public Class ClassBase
End Class

Public Class ClassA
  Inherits ClassBase
End Class

Public Class ClassACollection
    Inherits System.Collections.ObjectModel.Collection(Of ClassA)
End Class

Public Class ClassB
  Inherits ClassBase
End Class

Public Class ClassBCollection
    Inherits System.Collections.ObjectModel.Collection(Of ClassB)
End Class

クラスMainをシリアル化するとDataContractSerializer、次のような XML が得られました。

<Main>
  <ListOfA>
    <ClassA>
      .....
    </ClassA>
    <ClassA>
      .....
    </ClassA>
  </ListOfA>
</Main>

最近、私は削除ClassAしましClassBたが、それらは同一でした! 両方のコレクションを削除して、これに置き換えました:

public class Main
    Public Property ListOfA As ClassBaseCollection
End Class

Public Class ClassBaseCollection
    Inherits System.Collections.ObjectModel.Collection(Of ClassBase)
End Class

しかし、XML をデシリアライズしようとすると、コレクションListOfAは作成されますが、常に空です。逆シリアル化中にエラーは発生しませんでした。

を使用しようとしましたDataContractResolverが、関数がorResolveNameを呼び出すことはありません。ClassAClassB

Dim dc As New Runtime.Serialization.DataContractSerializer(GetType(Main), Nothing, Integer.MaxValue, False, True, Nothing, New MyResolver())

Private Class MyResolver
    Inherits Runtime.Serialization.DataContractResolver

    Public Overrides Function ResolveName(typeName As String, typeNamespace As String, declaredType As System.Type, knownTypeResolver As System.Runtime.Serialization.DataContractResolver) As System.Type
      If typeName.Equals("ClassA") OrElse typeName.Equals("ClassB") Then
        Return GetType(ClassBase)
      Else
        'Defer to the known type resolver
        Return knownTypeResolver.ResolveName(typeName, typeNamespace, Nothing, Nothing)
      End If
  End Function
End Class

DataContractResolver私がやりたいことをするのに良い方法ですか?はいの場合、作業を行うために他に何か必要DataContractResolverですか?

ご協力いただきありがとうございます!


更新:次のテストを実行するためにプロジェクトに戻っClassAて 追加しました: - それらを既知のデータ型としてコンストラクター に配置しようとしました。 - ClassBaseCollection` で試してみました。ClassB
DataContractSerializer
KnownTypeAttribute

この 2 つの状況では、ResolveNameと はまだ呼び出されていませClassAClassB

から派生したクラスを使用IDataContractSurrogateして関数の型を変換しようとしましたが、この関数はandGetDataContractTypeに対して呼び出されません。ClassAClassB


更新 #2: 最後に、やりたいことを行う方法が見つかりませんでした。シリアル化する前に、ファイルのバージョンを確認し、XML 内の古いタグを新しいタグに置き換える必要がありました。元。:

data = data.Replace("<ClassA>", "<ClassBase>")
...

これは私の最初の質問に対する回答ではなく、回避策です。

4

1 に答える 1

1

しかし、XML を逆シリアル化しようとすると、コレクションListOfAは作成されますが、常に空です。逆シリアル化中にエラーは発生しませんでした。

データ コントラクトのバージョン管理に関する msdn のドキュメントでは、ListOfA空である理由に関する情報を見つけることができます。調整されたバージョンの逆シリアル化エンジンは、このデータを解釈できないClassAか、破棄します。ClassB

Data Contract Resolverを使用して正しい追跡をしていると思います。

データ コントラクト リゾルバーを使用すると、既知の型を動的に構成できます。データ コントラクトで想定されていない型をシリアル化または逆シリアル化する場合は、既知の型が必要です

コンストラクターの既知のデータ型パラメーターでClassAandを指定しなかったため、は呼び出されません。既知のデータ型の詳細については、msdn ドキュメント を確認してください。つまり、これらの古いクラスを正しく逆シリアル化するには、下位互換性のためにそれらを含める必要があります。ClassBDataContractSerializerResolveName()

于 2012-11-20T15:20:54.523 に答える