[C++/CLI] Deserializarea membrilor avind semantica de stiva

Limbajul C++/CLI, applicatii mixed-mode sau probleme specifice .NET legate de C++ (forum moderat)
Post Reply
Viorel
Microsoft MVP
Microsoft MVP
Posts: 286
Joined: 13 Jul 2007, 12:26

[C++/CLI] Deserializarea membrilor avind semantica de stiva

Post by Viorel » 29 Dec 2008, 16:23

Deserializarea membrilor avînd semantica de stivă

Fie avem o clasă A:

Code: Select all

ref class A
{
public:
	int x;

	A()
	{
		x = 1234;
	}
};
Aceasta va fi folosită drept membru al clasei B. Fie clasa B este serializabilă, iar membrul de tip A este declarat neserializabil:

Code: Select all

[Serializable]
ref class B
{
public:
	int y;

	[NonSerialized]
	A a;
};
În mod intenţionat, membrul a este declarat fără simbolul „^”, astfel avînd semantica de stivă (stack semantics). În limbajul C++ acest tip de variabile presupune alocarea şi dealocarea automată a obiectelor cu ajutorul gcnew şi respectiv delete. În exemplul de mai sus, în linia „A a;” compilatorul creează de fapt o referinţă „A ^ a;” şi adaugă cod pentru gestionarea acesteia [http://msdn.microsoft.com/en-us/library/ms177191.aspx].

Să declarăm o variabilă de tip B şi să o serializăm într-un flux. Pentru simplitate vom folosi unul alocat în memorie:

Code: Select all

B ^ b = gcnew B;
b->y = 5678;

// Serializare
MemoryStream ^ ms = gcnew MemoryStream;
BinaryFormatter ^ bf = gcnew BinaryFormatter;
bf->Serialize(ms, b);
Să refacem variabila b prin deserializare din acelaşi flux:

Code: Select all

// Deserializare
ms->Position = 0;
b = (B^)bf->Deserialize(ms);
Să verificăm rezultatele deserializării:

Code: Select all

int y = b->y; // 5678 -- corect
int x = b->a.x; // eroare: NullReferenceException
Valoarea lui y este 5678, deci este deserializată corect.

Deoarece membrul a este neserializabil, ne aşteptăm ca după deserializare valoarea acestuia să fie cea implicită, definită de constructor. Însă încercarea de citire a membrului a eşuează -- se generează excepţia NullReferenceException. Evident nu b este cel care e nul. Este vorba de acea referinţă ascunsă generată de compilator pentru membrul a. Şi nici nu este posibilă refacerea manuală a membrului a, deoarece expresiile b->a = gcnew A şi b->a = *gcnew A sînt eronate.

Prin urmare membrii neserializabili avînd semantica de stivă se pierd în urma operaţiilor de deserializare, făcînd imposibilă utilizarea ulterioară a obiectelor deserializate.

Sursa: http://social.msdn.microsoft.com/Forums ... 63e133361f.


Next FAQ >>



Post Reply