Versionable schema

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Versionable schema

Post by mesajflaviu » 28 Oct 2011, 11:30

Am o aplicatie SDI, de test, in care am vrut sa serializez un fisier de versine 2 sa zicem :

Code: Select all

class CData : public CObject  
{
	DECLARE_SERIAL(CData)
public:
	CData();
	virtual ~CData();

	virtual void Serialize(CArchive& ar);

	BOOL ReadDocumentFromDisk();
	BOOL WriteDocumentToDisk();
};
si implementarea :

Code: Select all

IMPLEMENT_SERIAL(CData, CObject, VERSIONABLE_SCHEMA | 2)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CData::CData()
{

}

CData::~CData()
{

}

void CData::Serialize(CArchive& ar)
{
	CString sMessage;
	CTestSerView* pView = CTestSerView::GetView();

	CObject::Serialize(ar);

	try
	{
		if(ar.IsLoading())
		{
			UINT uVersion = ar.GetObjectSchema();
			int n = 0;
			ar >> n;
			sMessage.Format(_T("The document is loading ... doc. value is %d and objectschema is %d\n"),n,uVersion);
		}
		else	// storing
		{
			sMessage.Format(_T("The document is storing ...\n"));
			int x = 456;	// just for testing
			ar << x;
		}
		pView->AppendLine(sMessage);
	}
	catch(CFileException* pFileException)
	{
		pFileException->ReportError();
		pFileException->Delete();
	}
}

BOOL CData::ReadDocumentFromDisk()
{
	CFile file;
	CString sFile;
	CFileException FileException;

	::GetModuleFileName(NULL,sFile.GetBuffer(255),255);
	sFile.ReleaseBuffer();
	sFile = sFile.Left(sFile.ReverseFind('\\') + 1);
	sFile += _T("Default.tse");

	if(! file.Open(sFile,CFile::modeRead,&FileException))
	{
		return FALSE;
	}

	CArchive ar(&file,CArchive::load);
	Serialize(ar);

	return TRUE;
}

BOOL CData::WriteDocumentToDisk()
{
	CFile file;
	CString sFile;
	CFileException* pFileException = NULL;

	::GetModuleFileName(NULL,sFile.GetBuffer(255),255);
	sFile.ReleaseBuffer();
	sFile = sFile.Left(sFile.ReverseFind('\\') + 1);
	sFile += _T("Default.tse");

	if(! file.Open(sFile,CFile::modeCreate | CFile::modeWrite,pFileException))
	{
		return FALSE;
	}

	CArchive ar(&file,CArchive::store);
	Serialize(ar);

	return TRUE;
}
iar din meniul view :

Code: Select all

void CTestSerView::OnHelpStore() 
{
	// TODO: Add your command handler code here

	CData data;
	data.WriteDocumentToDisk();
}

void CTestSerView::OnHelpLoad() 
{
	// TODO: Add your command handler code here

	CData data;
	data.ReadDocumentFromDisk();
}
dar nu se serializeaza versinea de document(2 in acest caz), de ce ? ... acuma stiu ca as putea realiza acest lucru manual, serializand manual o variabila int, pe care s-o citesc la incarcarea documentului, etc. ... dar as vrea sa folosesc toate capabilitatile MFC-ului ...

Mentionez ca o cerinta e sa nu serializez acest document prin CDocument::Serialize (CTestSerDoc::Serialize).
Atasez si un proiect de test, pentru exemplificare.
Attachments
TestSer.zip
(85.12 KiB) Downloaded 276 times



Viorel
Microsoft MVP
Microsoft MVP
Posts: 293
Joined: 13 Jul 2007, 12:26

Re: Versionable schema

Post by Viorel » 28 Oct 2011, 12:09

Încearcă următoarele procedee de serializare şi deserializare:

Code: Select all

--- Serializare ---

CData * data = new CData;

CFile file(_T("Test.tse"), CFile::modeCreate | CFile::modeWrite);
CArchive ar(&file, CArchive::store);

ar << data;

delete data;


--- Deserializare ---

CData * data;

CFile file(_T("Test.tse"), CFile::modeRead);
CArchive ar(&file, CArchive::load);

ar >> data;
. . .
delete data;
Versiunea specificată cu VERSIONABLE_SCHEMA are efect dacă se folosesc pointeri şi operatorii '<<' şi '>>' în loc de Serialize.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Versionable schema

Post by Ovidiu Cucu » 28 Oct 2011, 13:18

Daca pui la inceput

Code: Select all

ar.SerializeClass(RUNTIME_CLASS(CData));
// ...
Atunci merge fara alte giumbuslucuri.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Versionable schema

Post by mesajflaviu » 28 Oct 2011, 14:26

Am incercat si eu

Code: Select all

ar.SerializeClass(RUNTIME_CLASS(CData));
dar nu la inceputul serializarii, si cum n-a mers, n-am mai stiut ce sa fac.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Versionable schema

Post by Ovidiu Cucu » 29 Oct 2011, 09:46

mesajflaviu wrote:Am incercat si eu

Code: Select all

ar.SerializeClass(RUNTIME_CLASS(CData));
dar nu la inceputul serializarii, si cum n-a mers, n-am mai stiut ce sa fac.
De ce nu la inceput?
Daca pasesti in cod ai sa vezi ca functia aia scrie/citeste in/din fisier informatii despre clasa obiectului pe care-l serializezi, incluzand versiunea.
Deci, or course ca trebie sa-l pui la inceputul lui Serialize.
Daca ai pus DECLARE_SERIAL si IMPLEMENT_SERIAL in clasa ta, ai deja supraincarcati ambii operatori, >> si <<.
In principiu fac acelasi lucru: mai intai scriu/citesc in/din fisier informatii despre clasa, dupa care apeleaza... Serialize.
Problema cu ei, asa cum a remarcat Viorel mai devreme, este ca sunt facuti special sa lucreze in framework-ul SDI/MDI, cu obiectele create dinamic.
In consecinta, pentru a-i folosi ar trebui sa folosesti si tu obiecte create dinamic si sa ai grija sa faci curatenie de oridecateori e nevoie, daca nu vrei sa te trezesti cu garla de memory leaks. Ceea ce, cred eu, nu-i prea comod.

O sa incerc sa fac o clasa de baza sa-i zicem CSerializableData care sa impace si capra si varza.
Pana atunci, ramanand la solutia cu Serialize + SerializeClass, poti arunca un ochi in articolul asta: http://www.codexpert.ro/articole.php?id=9

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Versionable schema

Post by Silviu Ardelean » 29 Oct 2011, 14:44

De la primul impact cu proiectul de test mi-a sarit in ochi metoda Serialize() din clasa document.

Code: Select all

void CTestSerDoc::Serialize(CArchive& ar)
{
	// CEditView contains an edit control which handles all serialization
	((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);
}
In metoda ta de serialize ar trebuii sa apelezi metoda Serialize din CData.

N-am inteles de ce vrei sa folosesti CTestSerView::OnHelpLoad() si void CTestSerView::OnHelpStore(). Banuesc ca vroiai de fapt OnFileSave() si OnFileOpen(). Totusi, nu e nevoie nici macar atat.

Da o geana aici si vezi cum scriu/citesc in clasa Contact (la tine CData) fara a a ma cobora la nivel de operatii pe disc. Las framework-ul MFC sa-si faca treaba.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Versionable schema

Post by Ovidiu Cucu » 29 Oct 2011, 17:15

@Silviu: eu am inteles ca omu vrea sa faca o serializare a ceva care nu are de-a face cu framework-ul SDI/MDI.
Pe unde a pus meniurile "Load" si "Store" sau ce-a facut sau n-a facut in CTestSerDoc::Serialize, nu are legatura cu restul problemei.
A facut doar o aplicatie de test la repezeala, cu ce i-a venit Wizard-ului mai la indemana. Oricum e mai bine decat nimic. :)

@mesajflaviu: am promis mai devreme o clasa care sa rezolve problemele pe care le-am discutat pana acum. Am atasat aici un proiectel.
CBaseData e o clasa abstracta din care poti deriva, adauga date dupa nevoi dupa care, obligatoriu, sa suprascrii si sa implementezi functia Serialize.
Metodele pentru serializare sunt StoreToFile si LoadFromFile.
Am supraincarcat si operatorul >> care primeste referinta la obiect si nu la pointer.
Exista si o metoda Dump care sa fie de ajutor la debug si/sau sa se vada ce anume se intampla.
Enjoy!

@Everybody: Daca sunt greseli, completari, solutii mai bune sau intrebari, va rog sa spuneti.
Attachments
Demo_Serialize.zip
(12.5 KiB) Downloaded 268 times

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Versionable schema

Post by Silviu Ardelean » 29 Oct 2011, 18:06

Ovidiu Cucu wrote:@Silviu: eu am inteles ca omu vrea sa faca o serializare a ceva care nu are de-a face cu framework-ul SDI/MDI.
Pe unde a pus meniurile "Load" si "Store" sau ce-a facut sau n-a facut in CTestSerDoc::Serialize, nu are legatura cu restul problemei.
"Am o aplicatie SDI, de test, in care am vrut sa serializez un fisier de versine 2 sa zicem" - se pare ca are toata ziua de-a face cu SDI/MDI iar incercarea de-a salva/incarca pe cele doua metode subliniate nu mi se pare deloc inspirata.
Din faptul ca in CTestSerDoc::Serialize() el apeleaza SerializeRaw() imi da de inteles ca Flaviu nu a renuntat la Serialize().
mesajflaviu wrote: dar nu se serializeaza versinea de document(2 in acest caz), de ce ? ... acuma stiu ca as putea realiza acest lucru manual, serializand manual o variabila int, pe care s-o citesc la incarcarea documentului, etc. ... dar as vrea sa folosesc toate capabilitatile MFC-ului ...

Mentionez ca o cerinta e sa nu serializez acest document prin CDocument::Serialize (CTestSerDoc::Serialize).
Atasez si un proiect de test, pentru exemplificare.
Ori serializam, ori nu mai serializam (SDI/MDI sau altfel...). :)
In aplicatia demo nu am vazut cod care sa faca distinctia intre cele doua versini. Se citeste versiunea si noapte buna. De setat nu se seteaza nicaieri (SetObjectSchema() lipseste cu desavarsire). De citit/scris informatiile efective cu atat mai putin.

PS. Cred ca intre aplicatia reala si ceea demo sunt niste diferente semnificative de implementare si detaliu. Doar Flaviu poate face mai multa lumina...

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Versionable schema

Post by Ovidiu Cucu » 30 Oct 2011, 12:01

Silviu Ardelean wrote: PS. Cred ca intre aplicatia reala si ceea demo sunt niste diferente semnificative de implementare si detaliu. Doar Flaviu poate face mai multa lumina...
Te-ai prins. :)

Acuma serios si revenind la clasele din primul meu exemplu. Nu ma impiedica nimeni de-acum sa le refolosesc exact asa cum sunt intr-un document din SDI/MDI, intr-o aplicatie MFC dialog-based sau intr-o aplicatie consola, daca asa vrea muschii mei.
Incalc prin asta vreo paradigma OOP sau MFC doc-view architecture? Eu cred ca nu, dimpotriva.

Atasez si un demo cu SDI.
Demo_Serialize_SDI.zip
(20.88 KiB) Downloaded 293 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Versionable schema

Post by mesajflaviu » 31 Oct 2011, 10:33

Cazul real cuprinde mai multe tipuri de documente (MDI), iar serializarea aceluiasi tip de obiect (CData, cu extensia '.data') ar trebui sa poata fi facuta din mai multe documente deschise ... de fapt aplicatia lucreaza cu date din 'fisertest.data' iar acestea trebuie citite/scrise din mai multe view-uri/doc-uri ale aplicatiei ... de aceea am avut nevoie de un obiect CData, care are propria metoda CData::Serialize(...), iar cu ajutorul ReadDocumentFromDisk(), WriteDocumentToDisk() sa am acces la obiectul CData serializat pe disc de oriunde din aplicatie.

In acest caz nu cred ca era suficienta serializarea acestui obiect, CData, in metoda Serialize(...) intr-o clasa document a aplicatiei ....

In proiectelul de test Demo_Serialize.zip se vede foarte bine asemanarea/diferenta intre cele moduri de a serializa un obiect.
Multumesc tuturor pentru indrumari !

Post Reply