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. 😉
you could override the == operator for your class, or override
Equalsand do the comparison viaa.Equals(b)to see if they are the same, rather than relying on the default equality based on address.