DataContractSerializerの逆シリアル化の深さを制御できますか?
-
03-07-2019 - |
質問
DataContractSerializerを介してファイルにシリアル化したかなり大きなオブジェクトグラフがあります。次に、これらのファイルのリストをユーザーに提示して、選択できるようにします。このリストでは、ルートオブジェクトのプロパティであるファイルに関する詳細の一部を表示します。ルートノードのプロパティの表示にのみ関心があるため、グラフ全体をメモリにロードしたくありません。
「深度」を制御する方法を知っている人はいますか?ファイルからルートオブジェクトを取得し、子をスキップできるように、逆シリアル化のファイルを未加工のXMLとして扱うことは避けたいと思います。未加工のXML操作を他のどこでも行っていないためです。
現時点で唯一のアイデアは、互換性のある「概要」を作成することです。興味のあるプロパティのみを含み、子を含まないオブジェクト、およびそのファイルへの逆シリアル化。子は要約オブジェクトに関連していないため、これは子をスキップする必要があります。
これを達成するためのより良い方法はありますか?
更新/明確化:属性は私が探している答えではありません。一つには、「余分な」ことを防ぎます。オブジェクトが最初にシリアル化されたときにファイルで終わるプロパティ。
第二に、彼らは私がやろうとしているものよりも永続的です。最終的には、この時点ではなく、ファイル全体を逆シリアル化したいと思います。ユーザーがインポート用に選択するファイルの要約リストを表示しようとしています。インポート中に、すべての子と孫が必要になります。手順1では単にやり過ぎです。これらは潜在的に大きなファイルであるため、ヘッダー情報を表示できるようにそれらのいくつかを完全に逆シリアル化することはできません。
うまくいけば、元の質問に関する混乱を解消できます。
解決
これは、ほぼあなたがやりたいことです。 DataContractSerializerは、この状況を処理することを目的としています。概念的には同じ型ですが、CLRの観点からは異なる型を相互にシリアル化する必要があります。
それを考えると、シリアル化するプロパティの同様のサブセットでオブジェクトを作成し、そのタイプをDataContractSerializerに渡すだけです。
" summary"で、 DataContract属性のプロパティ(および公開する子のDataMember属性またはDataContract属性)を設定するタイプ、具体的には、非要約タイプの名前とネームスペースを反映するNameおよびNamespaceプロパティ(これらは一致する必要があるため) 。
他のヒント
最初の推奨事項は、単にルートノードから詳細を引き出したい場合にXML操作を行うことです。もう1つの可能性は、パフォーマンスの意味がわかりませんが、この問題にDataContractSerializerのバージョン管理機能を使用することです。データコントラクトで、サマリーに必要なフィールドを除くすべてのフィールドをオプションとしてマークします。次に、データコントラクトを別のクラスとしてコピーし、オプションのフィールドを省略します。新しい、より小さなデータコントラクトにデシリアライズします。
class Program
{
static void Main(string[] args)
{
Person a = new Person();
Person b = new Person();
a.Name = "Mike";
b.Name = "Joe";
b.Parent = a;
DataContractSerializer dtc = new DataContractSerializer(typeof(Person));
StringBuilder sb = new StringBuilder();
using (XmlWriter xr = XmlWriter.Create(sb))
{
dtc.WriteObject(xr, b);
}
object n;
DataContractSerializer dtc2 = new DataContractSerializer(typeof(TinyPerson));
using (XmlReader xr = XmlReader.Create(new StringReader(sb.ToString())))
{
n = dtc2.ReadObject(xr);
}
}
}
[DataContract(Name="Person")]
public class Person
{
[DataMember]
public string Name;
[DataMember(IsRequired=false)]
public Person Parent;
}
[DataContract(Name = "Person")]
public class TinyPerson
{
[DataMember]
public string Name;
}
属性を使用して、シリアル化を制御できます。 続きを読むこちら