为什么ASP.NET视图状态会丢失序列化对象的标识?

时间:2011-05-19 09:00:13

标签: .net asp.net serialization viewstate object-identity

简短问题:当我将一个对象的同一个实例放在viewstate中两次时,反序列化时有两个实例。我希望那里只有一个例子。可以这样做吗?

Wordy解释:

请考虑以下代码:

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”。也就是说,虽然我在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);
        }
    }
}

现在我收到消息“False”和“True”(按此顺序)。再次,检查Viewstate显示,每个对象被序列化两次。是什么赋予了?我用ILSpy检查了System.Web.UI.StateBag的来源,但它只是将所有值都推送到ArrayList,并且没有特殊的序列化代码。那么无论是谁序列化视图状态(System.Web.UI.ObjectStateFormatter?)都以某种方式将每个对象和序列化作为一个单独的图...为什么???我可以解决它吗?

更新:我需要这个的原因是同一个对象将由两个独立的组件持久化,并且在反序列化时我想检查它们是否具有相同的对象。 (或者更确切地说,它们都存储了对象本身的集合,我需要同步这些集合。)

我可以通过十几种不同的方式实现自定义比较,但由于我想为任意对象执行此操作,因此有点棘手。 ;)

2 个答案:

答案 0 :(得分:2)

您可以覆盖您的类的==运算符,或覆盖Equals并通过a.Equals(b)进行比较以查看它们是否相同,而不是依赖于基于地址的默认相等性。

答案 1 :(得分:2)

Viewstate是一本字典,就是它的运作方式。如果你想存储相同的值,只有你应该写入相同的“密钥”,这将覆盖以前的值。

你也通过a.Equals(b)

尝试你的平等比较