1

短い質問:オブジェクトの同じインスタンスをビューステート内に 2 回配置すると、逆シリアル化時に 2 つのインスタンスが存在します。1 つのインスタンスだけが必要です。これはどのように行うことができますか?

冗長な説明:

次のコードを検討してください。

public partial class MyControl : System.Web.UI.UserControl
{
    [Serializable]
    class MyClass
    {
        public string x;
    }
    public void Page_Load(object sender, EventArgs e)
    {
        if (this.IsPostBack)
        {
            MyClass a = (MyClass)this.ViewState["a"];
            MyClass b = (MyClass)this.ViewState["b"];
            MessageManager.Show((a == b).ToString(), MessageSeverity.Debug);
        }
        else
        {
            var x = new MyClass() { x = "stackoverflow" };
            this.ViewState["a"] = x;
            this.ViewState["b"] = x;
            MessageManager.Show("Init", MessageSeverity.Debug);
        }
    }
}

それが実行され、ポストバックが開始されると、「false」というメッセージが表示されます。つまり、ビューステート内に 1 つのオブジェクトを配置しましたが、2 回シリアル化されました。これは、viewstate の内容を調べることで確認できます。

相互参照オブジェクトをビューステートに配置しようとすると、各項目が個別のグラフとしてシリアル化されます。説明する:

public partial class MyControl : System.Web.UI.UserControl
{
    [Serializable]
    class MyClass
    {
        public string x;
        public MyClass other;
    }
    public void Page_Load(object sender, EventArgs e)
    {
        if (this.IsPostBack)
        {
            MyClass a = (MyClass)this.ViewState["a"];
            MyClass b = (MyClass)this.ViewState["b"];
            MessageManager.Show((a.other == b).ToString(), MessageSeverity.Debug);
            MessageManager.Show((a.other.other == a).ToString(), MessageSeverity.Debug);
        }
        else
        {
            var a = new MyClass() { x = "stack" };
            var b = new MyClass() { x = "overflow" };
            a.other = b;
            b.other = a;
            this.ViewState["a"] = a;
            this.ViewState["b"] = b;
            MessageManager.Show("Init", MessageSeverity.Debug);
        }
    }
}

これで、「False」と「True」というメッセージが (この順序で) 表示されます。ここでも、Viewstate を調べると、各オブジェクトが 2 回シリアル化されていることがわかります。何を与える?のソースSystem.Web.UI.StateBagを ILSpy で確認しましたが、すべての値を にプッシュするだけで、ArrayList特別なシリアル化コードもありません。したがって、viewstate をシリアル化する人 ( System.Web.UI.ObjectStateFormatter?) は、どういうわけか各オブジェクトを取得し、個別のグラフとしてシリアル化しています...なぜですか? そして、私はそれを回避できますか?

更新:これが必要な理由は、同じオブジェクトが 2 つの別々のコンポーネントによって永続化され、逆シリアル化時にそれらが同じオブジェクトを持っているかどうかを確認したいからです。(というか、どちらもオブジェクト自体のコレクションを格納しており、それらのコレクションを同期する必要があります)。

さまざまな方法でカスタム比較を実装できますが、これを任意のオブジェクトに対して実行したいので、ややこしくなります。;)

4

2 に答える 2

2

Viewstate はディクショナリであり、それが意図された動作方法です。同じ値を保存して一度だけ使用したい場合は、同じ「キー」に書き込む必要があります。これにより、以前の値が上書きされます。

また、 a.Equals(b) を実行して等価比較を試みましたか

于 2011-05-19T09:09:34.433 に答える
2

アドレスに基づくデフォルトの等価性に頼るのではなく、クラスの == 演算子をオーバーライドするか、オーバーライドEqualsして比較を行い、それらが同じかどうかを確認することができます。a.Equals(b)

于 2011-05-19T09:09:19.437 に答える