1

ユーザーがアプリケーションをホストしているページから離れたときに設定を保存するために、Silverlight 3 で IsolatedStorage を使用しています。

現在、私は DataContractSerializer を使用して設定をファイルに書き込んでいます。状況によっては、結果のファイルが 10 MB を超える非常に大きくなります (このサイズの多くは、シリアライザー自体とそれが生成する XML によるものです)。これにより問題が発生します。

  • ユーザーに追加のスペースを要求する必要があります
  • ファイルへのデータの書き込みが本当に遅い

IsolatedStorage でより大きなファイルを処理するために使用したいくつかの戦略を誰かが共有できますか?

  • 必要になる可能性のあるディスク容量をどのように決定しますか?
  • DataContract または Xml Serializer を使用して、保存する前に結果を圧縮しますか?
  • または、ある種のバイナリ/カスタムシリアライゼーションを使用していますか? もしそうなら、スペースや時間を大幅に節約できましたか?
  • ユーザーが任意の時点でプロンプトを表示する必要がないように、アプリケーションに特定のクォータが必要であることを宣言的に示す方法はありますか?

個人的には、このように大量のデータをファイルに書き込むのは好きではありませんが、製品マネージャーに問題を説明して要件を変更するよう説得する前に、利用可能なすべてのオプションを知る必要があります。

ありがとう!

4

5 に答える 5

4

スラッグスター、

代わりに、XMLSerializerへの切り替えを検討することをお勧めします。これが私が時間をかけて決定したことです:

XMLSerializerクラスとDataContractSerializerクラスは、XMLとの間でオブジェクトグラフをシリアル化および逆シリアル化する簡単な手段を提供します。

主な違いは次のとおり
です。1。
[XmlElement]の代わりに[XmlAttribute]を使用すると、XMLSerializerのペイロードはDCSよりもはるかに小さくなります 。DCSは
常に値を要素として格納します。2。DCS は「オプトアウト」ではなく「オプトイン」 です。 [DataMember]でシリアル化するものを明示的にマークするDCSを使用する と、保護またはプライベートとしてマークされている場合でも、任意のフィールドまたはプロパティをシリアル化 できます。DCSを使用すると、[IgnoreDataMember]を使用してシリアライザーに特定のプロパティを無視させることができます。





XMLSerializerを使用すると、パブリックプロパティがシリアル化され、セッターを逆シリアル化する必要があり
ます。XmlSerializerを使用すると、[XmlIgnore]を使用して、シリアライザーにパブリックプロパティを無視させることができ ます

DCS.ReadObjectは、逆シリアル化中にコンストラクターを呼び出さない
初期化を実行する必要がある場合、DCSは次のコールバックフックをサポートします:
[OnDeserializing]、[OnDeserialized]、[OnSerializing]、[OnSerialized]
(バージョン管理の問題の処理にも役立ちます

) 2つのシリアライザーを切り替える機能では、次のように、両方の属性セットを同時に使用できます。

[DataContract]
[XmlRoot]
    public class ProfilePerson : NotifyPropertyChanges
    {
[XmlAttribute]
[DataMember]
        public string FirstName { get { return m_FirstName; } set { SetProperty(ref m_FirstName, value); } }
        private string m_FirstName;
[XmlElement]
[DataMember]
        public PersonLocation Location { get { return m_Location; } set { SetProperty(ref m_Location, value); } }
        private PersonLocation m_Location = new PersonLocation(); // Should change over time
[XmlIgnore]
[IgnoreDataMember]
        public Profile ParentProfile { get { return m_ParentProfile; } set { SetProperty(ref m_ParentProfile, value); } }
        private Profile m_ParentProfile = null;

        public ProfilePerson()
        {
        }
    }

また、2つを切り替えることができる私のSerializerクラスをチェックしてください:

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ClassLibrary
{
    // Instantiate this class to serialize objects using either XmlSerializer or DataContractSerializer
    internal class Serializer
    {
        private readonly bool m_bDCS;

        internal Serializer(bool bDCS)
        {
            m_bDCS = bDCS;
        }

        internal TT Deserialize<TT>(string input)
        {
            MemoryStream stream = new MemoryStream(input.ToByteArray());
            if (m_bDCS)
            {
                DataContractSerializer dc = new DataContractSerializer(typeof(TT));
                return (TT)dc.ReadObject(stream);
            }
            else
            {
                XmlSerializer xs = new XmlSerializer(typeof(TT));
                return (TT)xs.Deserialize(stream);
            }
        }

        internal string Serialize<TT>(object obj)
        {
            MemoryStream stream = new MemoryStream();
            if (m_bDCS)
            {
                DataContractSerializer dc = new DataContractSerializer(typeof(TT));
                dc.WriteObject(stream, obj);
            }
            else
            {
                XmlSerializer xs = new XmlSerializer(typeof(TT));
                xs.Serialize(stream, obj);
            }

            // be aware that the Unicode Byte-Order Mark will be at the front of the string
            return stream.ToArray().ToUtfString();
        }

        internal string SerializeToString<TT>(object obj)
        {
            StringBuilder builder = new StringBuilder();
            XmlWriter xmlWriter = XmlWriter.Create(builder);
            if (m_bDCS)
            {
                DataContractSerializer dc = new DataContractSerializer(typeof(TT));
                dc.WriteObject(xmlWriter, obj);
            }
            else
            {
                XmlSerializer xs = new XmlSerializer(typeof(TT));
                xs.Serialize(xmlWriter, obj);
            }

            string xml = builder.ToString();
            xml = RegexHelper.ReplacePattern(xml, RegexHelper.WildcardToPattern("<?xml*>", WildcardSearch.Anywhere), string.Empty);
            xml = RegexHelper.ReplacePattern(xml, RegexHelper.WildcardToPattern(" xmlns:*\"*\"", WildcardSearch.Anywhere), string.Empty);
            xml = xml.Replace(Environment.NewLine + "  ", string.Empty);
            xml = xml.Replace(Environment.NewLine, string.Empty);
            return xml;
        }
    }
}

幸運、
ジム・マッカーディ

対面ソフトウェアYinYangMoney

于 2010-02-01T16:56:55.457 に答える
1

オブジェクト グラフの適度にコンパクトな表現を作成する、Silverlight と .NET 用のコンパクトなバイナリ シリアライザー クラスがあります。同じ理由 (および WCF サービスにネットワーク経由でデータを送信するコスト) で、それを作成する必要がありました。

コードと詳細な説明は私のブログにあります。

于 2010-09-15T10:32:56.777 に答える
1

もう 1 つの方法は、xml シリアライゼーションのコンテンツを圧縮することです。また、大まかな圧縮率が 10 対 1 の大きな連載もあります。もちろん、圧縮にはかなりの量の CPU が必要です。ユーザー インターフェイスの速度が低下しないように、スレッド内で圧縮を生成します。Silverlight で動作する変更された SharpZipLib を使用しています。

于 2010-02-01T17:02:17.657 に答える
1

別のオプションは、json にシリアル化することです。パフォーマンスについてはわかりませんが、エンティティのかなり複雑なリストを json と xml にシリアル化したときの出力を比較したところ、json の方がはるかにコンパクトです。json を使用すると、結果の文字列は 1301303 バイトになりました。xml だと 2429630 です。json を使うとほぼ半分のサイズになります。

以下は、json にシリアル化/逆シリアル化するときに使用するヘルパー クラスです。

EDIT
いくつかのパフォーマンステストを行いましたが、実際にはjsonも高速であることがわかりました。xml では、10000 個のオブジェクトをシリアル化するのに 636 ミリ秒かかりましたが、json はわずか 257 ミリ秒でした。xml ではなく json を選択しない理由があるかどうか知っている人はいますか?

編集
今回は実際のデータを使用して再度テストしました:
(1000 オブジェクト)
圧縮されていない json: 605 kb
圧縮されていない xml: 3,53 MB (!)圧縮された json:
28,5 kb 圧縮された xml: 69,9 kb 事前に初期化されたシリアライザーを使用した場合の
パフォーマンス
:
json: ~350 ミリ秒
xml: ~120 ミリ秒

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;
using System.Runtime.Serialization.Json;

namespace GLS.Gui.Helper
{
    public static class SerializationHelper
    {
        public static string SerializeToJsonString(object objectToSerialize)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(objectToSerialize.GetType());
                serializer.WriteObject(ms, objectToSerialize);
                ms.Position = 0;

                using (StreamReader reader = new StreamReader(ms))
                {
                    return reader.ReadToEnd();
                }
            }
        }
        public static T Deserialize<T>(string jsonString)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));

                return (T)serializer.ReadObject(ms);
            }
        }

    }
}
于 2010-02-02T08:59:03.587 に答える
0

もう1つのオープンソースシリアライザーはSharpSerializerです。非常に複雑な構造でもバイナリ形式にシリアル化できます。それらを属性で前にマークする必要はありません。さらに、データをXmlにシリアル化することもできます。つまり、デバッグ用です。

于 2011-08-07T06:50:49.917 に答える