views:

167

answers:

3

I'm using SerializableAttribute to write an object jack to disk. The object has a member department which references a static field accounts of another class Department. On deserializing, I find that the member department of the deserialized object no longer points to the same object as the static field accounts but now points to another identical copy.

All classes and objects involved are reference types. How do I get around this?

(Sorry about long code post.)

#include "stdafx.h"

using namespace System;
using namespace System::IO;
using namespace System::Runtime::Serialization;
using namespace System::Runtime::Serialization::Formatters::Binary;

[Serializable]
ref class Department {
 static Department(){ accounts = gcnew Department(L"Accounts"); }
public:
 static Department ^accounts;
 // similarly other departments come here...

 String ^name;
 Department(String ^name) : name(name) { }
};

[Serializable]
ref class Employee {
public:
 String ^name;
 Department ^department;

 Employee(String ^name, Department ^department) : name(name),
  department(department) { }

};

int main(array<System::String ^> ^args)
{
 Employee ^jack;
 IFormatter ^formatter = gcnew BinaryFormatter();

 String ^option = Console::ReadLine();
 if(option == L"read"){
  Stream ^stream = gcnew FileStream(L"dingdong.bin", FileMode::Open,
   FileAccess::Read, FileShare::Read);
  jack = (Employee^) formatter->Deserialize(stream);

  if(jack->department != Department::accounts)
   Console::WriteLine(L"Different objects");
  else
   Console::WriteLine(L"The same object");
  stream->Close();
  Console::ReadLine();
 }
 else {
  jack = gcnew Employee(L"Jack", Department::accounts);
  Stream ^stream = gcnew FileStream(L"dingdong.bin", FileMode::Create,
   FileAccess::Write, FileShare::None);
  formatter->Serialize(stream, jack);
  stream->Close();
 }

 return 0;
}

Edit: Added example code

A: 

I don't think you do. When you serialize, a serialized copy of the current value of f's static field. When this is deserialized, an object of the relevant type is created and its values hydrated from the serialized data. These may be reference types, but serialization is about transferring the values of objects between A and B, not their references.

You are saving to disk. How do you even know that f and its static field are still going to be in scope when you load from disk and deserialize?

David M
A: 

If you look up the [NonSerialized] attribute documentation, I think you'll find this example there.


Ok, now that you've posted the code, the problem becomes more clear. You should separate out the static part of the Department class into a Departments class. A list or enumeration of departments has nothing to do with the individual Department objects.

John Saunders
+2  A: 

In the simplest case, [NonSerialized] with IDeserializationCallback to restore the reference will do the trick. You can serialize a department code instead. Generally, if you need to serialize such singleton-like objects, you can serialize the referring object manually and substitute a «reference» object, which implements IObjectReference, or, possibly, use serialization surrogates instead of manual serialization to substitute the «reference» object.

PS: generally, I wouldn't recommend using default binary serialization for anything serious, because of various assembly-binding and versioning problems it tends to produce. In short, serialization is difficult, and cannot be simplified much.

Anton Tykhyy