【问题标题】:Why does ASP.NET viewstate lose identity of serialized objects?为什么 ASP.NET 视图状态会丢失序列化对象的标识?
【发布时间】:2011-08-28 16:59:23
【问题描述】:

小问题:当我将一个对象的同一个实例放入视图状态两次时,反序列化时会有两个实例。我希望只有一个实例。这可以做到吗?如何做到?

冗长的解释:

考虑以下代码:

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”。也就是说,虽然我在视图状态中放置了一个对象,但它被序列化了两次。这可以通过检查视图状态内容来验证。

如果我尝试将交叉引用对象放在视图状态中,那么每个项目都会被序列化为单独的图形。举例说明:

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?),都会以某种方式将每个对象序列化为一个单独的图......为什么?我可以解决它吗?

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

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

【问题讨论】:

  • @leppie - 这就是特定序列化的工作方式;这不一定适用于其他人

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


【解决方案1】:

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

【讨论】:

  • 是的,我知道这一点,但是我需要为我打算放在那里的每个对象实现自定义比较。如果可能的话,我想要更优雅的东西。
  • 是的,我想会是这样,只是指出明显的情况,以防万一没有更好的解决方案出现,并且将来有人路过。
  • 我会接受你的回答,尽管我没有覆盖 Equals,而是创建了一个自定义的 IEqualityComparer。侵入性较小。
【解决方案2】:

Viewstate 是一本字典,这就是它的预期运作方式。如果您想存储相同的值并且只拥有一次,您应该写入相同的“键”,这将覆盖以前的值。

您是否也通过执行 a.Equals(b) 来尝试进行相等比较

【讨论】:

  • 查看更新。而且我不明白为什么要这样操作。事实上,我会说这很违反直觉。如果我把同样的东西放进去两次,我希望把同样的东西拿出两次。它是否记录在任何地方?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-03
  • 2019-07-18
  • 2017-07-23
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多