Short question: When I put one and the same instance of an object inside viewstate twice, upon deserialization there are two instances. I want there to be just one instance. Can this be done and how?
Wordy explanation:
Consider the following code:
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);
}
}
}
When it is run, and a postback is initiated, I get the message "false". That is, although I put a single object inside the viewstate, it got serialized twice. This can be verified by inspecting viewstate contents.
If I try to put cross-references objects in viewstate, then each item gets serialized as separate graph. To illustrate:
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);
}
}
}
Now I get the messages "False" and "True" (in that order). Again, inspecting Viewstate shows, that each object got serialized twice. What gives? I checked the source of System.Web.UI.StateBag
with ILSpy, but it just pushes all the values into an ArrayList
, and that has no special serializing code either. So whoever is serializing the viewstate (System.Web.UI.ObjectStateFormatter
?) is somehow taking each object and serializing as a separate graph... why??? And can I work around it?
Update: The reason I need this is that the same object will be persisted by two separate components, and upon deserialization I would like to check if they have the same object. (Or rather, they both store collections of objects themselves, and I need to synchronize those collections).
I could implement custom comparison in a dozen different ways, but since I want to do this for arbitrary objects, it kinda gets tricky. ;)