Почему ASP.NET viewstate теряет идентичность сериализованных объектов? - PullRequest
1 голос
/ 19 мая 2011

Короткий вопрос: Когда я помещаю один и тот же экземпляр объекта в viewstate дважды, при десериализации есть два экземпляра.Я хочу, чтобы был только один экземпляр.Можно ли это сделать и как?

Объемное объяснение:

Рассмотрим следующий код:

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);
        }
    }
}

При запуске и обратной передачеинициируется, я получаю сообщение «ложь».То есть, хотя я поместил один объект в viewstate, он был сериализован дважды.Это можно проверить путем проверки содержимого viewstate.

Если я попытаюсь поместить объекты перекрестных ссылок в 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);
        }
    }
}

Теперь я получаю сообщения «Ложь» и «Истина» (в таком порядке).Опять же, проверка Viewstate показывает, что каждый объект был сериализован дважды.Что дает?Я проверил источник System.Web.UI.StateBag с помощью ILSpy, но он просто помещает все значения в ArrayList, и в нем также нет специального кода сериализации.Так что, кто бы ни сериализует состояние представления (System.Web.UI.ObjectStateFormatter?), Он каким-то образом берет каждый объект и сериализует как отдельный граф ... почему ???И можно ли обойти это?

Обновление: Причина, по которой мне это нужно, заключается в том, что один и тот же объект будет сохраняться двумя отдельными компонентами, и после десериализации я хотел бы проверить, есть ли у нихтот же объект.(Или, скорее, они оба хранят коллекции объектов сами, и мне нужно синхронизировать эти коллекции).

Я мог бы реализовать пользовательское сравнение десятком различных способов, но, поскольку я хочу сделать это для произвольных объектов, этовроде становится сложно.;)

Ответы [ 2 ]

2 голосов
/ 19 мая 2011

Viewstate - это словарь, который предназначен для работы.Если вы хотите сохранить одно и то же значение и иметь его только один раз, вы должны записать в тот же «ключ», который перезапишет предыдущее значение.

Также вы попытались сравнить равенство, выполнив a.Equals (b)

2 голосов
/ 19 мая 2011

вы можете переопределить оператор == для вашего класса или переопределить Equals и выполнить сравнение с помощью a.Equals(b), чтобы увидеть, совпадают ли они, вместо того, чтобы полагаться на равенство по умолчанию на основе адреса.

...