Prev: https://accountservices.msn.com/EmailPage.srf?emailid=5d4c1ef525bf
Next: Reminder - Microsoft Responds to the Evolution of Community
From: RB on 20 Jun 2010 10:51 Well I have done a bit more study and experimenting and I have 3 questions. Appreciate input from everyone as usual and hopefully Goran will also reply since he has helped me the most on serialization and from going back and rereading the context of his replies (after I studying and experimenting enough to even understand them) I can tell the he has a firm grasp on what is going on in MFC's serialization process. , My first question is, I can not help but wonder why MFC does not generate the Doc class (derived from CDocument) with the Serial macros as opposed to the Dyncreate. Like at first I was thinking of creating a whole other class derived from CObject with implement serial just to hold members I wanted a schema to, but then Goran gave an example of the mfc schema with creating the DocClass with SERIAL and after he showed this to me I began to wonder why MFC did not generate it that way ? Maybe because of ...... ( Goran did not recommend it since this ties serialization with your document class name, so you could have trouble changing it using of serializeClass or operator<</>> and might be a problem if a major overhaul of serialization occurs) 2 other questions below, denoted with ************ one simple mfc comment queston and another question on 2nd set of code at bottom. -------Implementing DocClass Serial instead of Dyncreate------ class CFileHandlingDoc : public CDocument { // RB question what exactly does this MFC generated comment mean ? // | | | ************ protected: // create from serialization only CFileHandlingDoc(); // DECLARE_DYNCREATE(CFileHandlingDoc) // RB doc creation with serial instead DECLARE_SERIAL(CFileHandlingDoc) .......... .......... } // CFileHandlingDoc implementations // IMPLEMENT_DYNCREATE(CFileHandlingDoc, CDocument) // RB creating doc with serial instead IMPLEMENT_SERIAL(CFileHandlingDoc, CDocument, 0) // And in my DocClass serialize function void CFileHandlingDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); ar << VerData.Ver << VerData.CpyRt << VerData.Corp; ar.SerializeClass(RUNTIME_CLASS(CMapStringToString)); ExpMap1.Serialize(ar); } else { ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); ar >> VerData.Ver >> VerData.CpyRt >> VerData.Corp; ar.SerializeClass(RUNTIME_CLASS(CMapStringToString)); ExpMap1.Serialize(ar); } } // The above compiles and works on writes and reads doc class // CRuntime Data with no problems ++++++++appreciate comments on below +++++++++++++ So then I am later reading in MFC Under the Hood by Laura Draxler on page 255 on the use of the SERIAL macros for user classes derived from CObject, she says: "It may seem inconsistent to you at first that document class does not need the SERIAL macros, and it uses the DYNCREATE macros instead, but the framework provides this support automatically for the document class." ---- And I am thinking yes it does seem that document class would use SERIAL. But I obviously have misunderstood the the context of her saying the framework provides serial for the doc class, since when I expanded the dyncreate macro and inserted my schema of 0 (instead of the default FFFF for dyncreate) the SerializeClass call failed on a read in. So she must be referring to another aspect of this. (see code expansion below) /////////////////////////////////////////////////// // CFileHandlingDoc // Seeing if framework provides serial under implement dyncreate ? // IMPLEMENT_DYNCREATE(CFileHandlingDoc, CDocument) // Expanded CObject* __stdcall CFileHandlingDoc::CreateObject() { return new CFileHandlingDoc; } const CRuntimeClass CFileHandlingDoc::classCFileHandlingDoc = { "CFileHandlingDoc", sizeof(class CFileHandlingDoc), 0x0000, // !RB replaced the 0xFFFF,! **************** CFileHandlingDoc::CreateObject, ((CRuntimeClass*)(&CDocument::classCDocument)), 0 }; CRuntimeClass* CFileHandlingDoc::GetRuntimeClass() const { return ((CRuntimeClass*)(&CFileHandlingDoc::classCFileHandlingDoc)); } // End Implement_Dyncreate expansion
From: Goran on 20 Jun 2010 13:02 On Jun 20, 4:51 pm, "RB" <NoMail(a)NoSpam> wrote: > Well I have done a bit more study and experimenting and I have 3 questions. Ok, you are going ahead of you now. You are not supposed to know the answer to all these questions so fast, you need 3 years MFC serialization experience first, minimum! ;-) > Appreciate input from everyone as usual and hopefully Goran will also reply > since he has helped me the most on serialization and from going back and > rereading the context of his replies (after I studying and experimenting enough > to even understand them) I can tell the he has a firm grasp on what is going on > in MFC's serialization process. , > My first question is, I can not help but wonder why MFC does not > generate the Doc class (derived from CDocument) with the Serial macros > as opposed to the Dyncreate. I guess simply because MFC does need _DYNCREATE (to create the document at runtime, from a template), but does not need _SERIAL, because MFC simply calls Serialize(ar); on the document class. Clearly, to simply call Serialize on an object, you don't need any of these macros. Now, remember, _SERIAL gives serialization operators >> and <<, and schema number. Since every serialization code I've seen so far has "global" document version, and some "magic" file type marker (your own does it), I proposed the use of DECLARE_SERIAL and SerializeClass simply because that will give you both, without reaching out for a custom solution. SerializeClass will store class name in the serialization stream (that's your "magic" file type marker), and will also store the version (that's... well, version). In all honesty: I came up with this idea of my own and I don't know if someone else does that. But I see no flaw in it. BTW, IIRC ;-)... If there's an error in the file (e.g. it's really something else, not your file), SerializeClass throws an exception with CArchiveException::badClass. That gets nicely reported in document's ReportStoreLoadException. > Like at first I was thinking of creating a whole > other class derived from CObject with implement serial just to hold members > I wanted a schema to, but then Goran gave an example of the mfc schema > with creating the DocClass with SERIAL and after he showed this to me I began > to wonder why MFC did not generate it that way ? Maybe because of ...... > ( Goran did not recommend it since this ties serialization with your document > class name, so you could have trouble changing it using of serializeClass or > operator<</>> and might be a problem if a major overhaul of serialization occurs) > > 2 other questions below, denoted with ************ > one simple mfc comment queston and > another question on 2nd set of code at bottom. > -------Implementing DocClass Serial instead of Dyncreate------ > > class CFileHandlingDoc : public CDocument > { > // RB question what exactly does this MFC generated comment mean ? > // | | | ************ > protected: // create from serialization only > CFileHandlingDoc(); Stupid and untrue wizard comments. ;-) I guess it wants to say: ctor is protected because this will be created from serialization only. But document will be created at runtime when creating a new document, too, so it's untrue that it's from serialization only. Only when document is open, "dynamic creation" AND seralization happen. > // DECLARE_DYNCREATE(CFileHandlingDoc) > // RB doc creation with serial instead > DECLARE_SERIAL(CFileHandlingDoc) > .......... > .......... > > } > > // CFileHandlingDoc implementations > > // IMPLEMENT_DYNCREATE(CFileHandlingDoc, CDocument) > // RB creating doc with serial instead > > IMPLEMENT_SERIAL(CFileHandlingDoc, CDocument, 0) Wow, wow, not like that! You need SERIALIZABLE_SCHEMA in there. I always start with SERIALIZABLE_SCHEMA|1, but I guess you can start with 0 as well. > > // And in my DocClass serialize function > void CFileHandlingDoc::Serialize(CArchive& ar) > { > if (ar.IsStoring()) > { > ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); No, that goes in front of the "if". Otherwise, you're calling it twice for no reason. See below, you do it already. > ar << VerData.Ver << VerData.CpyRt << VerData.Corp; > ar.SerializeClass(RUNTIME_CLASS(CMapStringToString)); > ExpMap1.Serialize(ar); > } > else > { > ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); > ar >> VerData.Ver >> VerData.CpyRt >> VerData.Corp; > ar.SerializeClass(RUNTIME_CLASS(CMapStringToString)); > ExpMap1.Serialize(ar); > } } > > // The above compiles and works on writes and reads doc class > // CRuntime Data with no problems > > ++++++++appreciate comments on below +++++++++++++ > So then I am later reading in MFC Under the Hood by > Laura Draxler on page 255 on the use of the SERIAL > macros for user classes derived from CObject, she says: > "It may seem inconsistent to you at first that document > class does not need the SERIAL macros, and it uses the > DYNCREATE macros instead, but the framework provides this > support automatically for the document class." I believe that this stems from a common misconception that you need XXX_SERIAL if you want to use serialization. Not necessarily. If all you want is to call Serialize, do it and forget XXX_SERIAL (in fact, you can often forget _DYNAMIC and _DYNCREATE, too). But schema changes get harder then ;-). As I explained before, MFC calls Serialize on the instance of the document class, but that's the end of it. It certainly does __not__ provide any additional support for document's serialization (logical, how can it know about stuff I want to save?). So if it's not calling SerializeClass, and it is not using << / >>, it does not need XXX_SERIAL, so why do it? I'd say that the explanation in the book is confusing at best. Goran.
From: Joseph M. Newcomer on 20 Jun 2010 18:01 See below... On Sun, 20 Jun 2010 10:51:39 -0400, "RB" <NoMail(a)NoSpam> wrote: > >Well I have done a bit more study and experimenting and I have 3 questions. >Appreciate input from everyone as usual and hopefully Goran will also reply >since he has helped me the most on serialization and from going back and >rereading the context of his replies (after I studying and experimenting enough >to even understand them) I can tell the he has a firm grasp on what is going on >in MFC's serialization process. , > My first question is, I can not help but wonder why MFC does not >generate the Doc class (derived from CDocument) with the Serial macros >as opposed to the Dyncreate. **** It does seem odd, but it also means that they are not assuming you require serialzation. I'd be in the other fix, having to constantly get rid of DECLARE/IMPLEMENT_SERIAL because I don't ever want to use the MFC serialization mechanism. It is often a coin-toss as to which choice is made. ***** > Like at first I was thinking of creating a whole >other class derived from CObject with implement serial just to hold members >I wanted a schema to, but then Goran gave an example of the mfc schema >with creating the DocClass with SERIAL and after he showed this to me I began >to wonder why MFC did not generate it that way ? Maybe because of ...... > ( Goran did not recommend it since this ties serialization with your document > class name, so you could have trouble changing it using of serializeClass or > operator<</>> and might be a problem if a major overhaul of serialization occurs) > >2 other questions below, denoted with ************ >one simple mfc comment queston and >another question on 2nd set of code at bottom. >-------Implementing DocClass Serial instead of Dyncreate------ > >class CFileHandlingDoc : public CDocument >{ > // RB question what exactly does this MFC generated comment mean ? > // | | | ************ >protected: // create from serialization only > CFileHandlingDoc(); > >// DECLARE_DYNCREATE(CFileHandlingDoc) >// RB doc creation with serial instead > DECLARE_SERIAL(CFileHandlingDoc) > .......... > .......... >} > >// CFileHandlingDoc implementations > >// IMPLEMENT_DYNCREATE(CFileHandlingDoc, CDocument) >// RB creating doc with serial instead > > IMPLEMENT_SERIAL(CFileHandlingDoc, CDocument, 0) > >// And in my DocClass serialize function >void CFileHandlingDoc::Serialize(CArchive& ar) >{ **** I have often felt this whole mechanism was designed by a totally clueless programmer. Probably the same twit that decided that we only needed UpdateData with a BOOL to indicate direction. I keep seeing this kind of horrid overloading of concepts in designs and wonder how it is that the same mistake gets repeated so often. In a sane worled, there would be SerializeIn(CArchive & ar) and SerializeOut(CArchive & ar). And the stupid IsStoring method would not have to exist. I think these are the same people who think that creating more files is evil. **** > if (ar.IsStoring()) > { > ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); > ar << VerData.Ver << VerData.CpyRt << VerData.Corp; > ar.SerializeClass(RUNTIME_CLASS(CMapStringToString)); > ExpMap1.Serialize(ar); > } > else > { > ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); > ar >> VerData.Ver >> VerData.CpyRt >> VerData.Corp; > ar.SerializeClass(RUNTIME_CLASS(CMapStringToString)); > ExpMap1.Serialize(ar); > } >} >// The above compiles and works on writes and reads doc class >// CRuntime Data with no problems > >++++++++appreciate comments on below +++++++++++++ >So then I am later reading in MFC Under the Hood by >Laura Draxler on page 255 on the use of the SERIAL >macros for user classes derived from CObject, she says: >"It may seem inconsistent to you at first that document >class does not need the SERIAL macros, and it uses the >DYNCREATE macros instead, but the framework provides this >support automatically for the document class." >---- >And I am thinking yes it does seem that document class >would use SERIAL. But I obviously have misunderstood >the the context of her saying the framework provides >serial for the doc class, since when I expanded the >dyncreate macro and inserted my schema of 0 (instead of >the default FFFF for dyncreate) the SerializeClass call >failed on a read in. So she must be referring to another >aspect of this. (see code expansion below) **** I have no idea. Serialize is so badly done I cannot imagine why I would ever want to use it. I knew about most of its problems in 1979, when we designed the LG system (think: XML done right), and I was apalled to find MFC had reinvented all the problems we knew were horrid problems decades before. All data should be tagged, self-identifying data. XML is a good representation for this. **** > >/////////////////////////////////////////////////// >// CFileHandlingDoc > >// Seeing if framework provides serial under implement dyncreate ? >// IMPLEMENT_DYNCREATE(CFileHandlingDoc, CDocument) >// Expanded > >CObject* __stdcall CFileHandlingDoc::CreateObject() > { > return new CFileHandlingDoc; > } > >const CRuntimeClass CFileHandlingDoc::classCFileHandlingDoc = > { "CFileHandlingDoc", sizeof(class CFileHandlingDoc), > 0x0000, // !RB replaced the 0xFFFF,! **************** **** Why? Just curious. **** > CFileHandlingDoc::CreateObject, > ((CRuntimeClass*)(&CDocument::classCDocument)), 0 > }; > >CRuntimeClass* CFileHandlingDoc::GetRuntimeClass() const > { > return ((CRuntimeClass*)(&CFileHandlingDoc::classCFileHandlingDoc)); > } >// End Implement_Dyncreate expansion Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: RB on 20 Jun 2010 19:25 > Goran wrote > I guess simply because MFC does need _DYNCREATE (to create the > document at runtime, from a template), but does not need _SERIAL, > because MFC simply calls Serialize(ar); on the document class. > Clearly, to simply call Serialize on an object, you don't need any of > these macros. RB replied Hey guy, thanks for replying. Yes I understand that the document doesn't necessarily "need" the Serial macro to write to file, but I couldn't understand why MFC would want to short the full capability of the schema in the doc. Or at least say why they did not. It just doesn't at first make sense from my limited view point, although see below for more. > Goran wrote > Now, remember, _SERIAL gives serialization operators >> and <<, and > schema number. Since every serialization code I've seen so far has > "global" document version, and some "magic" file type marker (your own > does it), I proposed the use of DECLARE_SERIAL and SerializeClass > simply because that will give you both, without reaching out for a > custom solution. SerializeClass will store class name in the > serialization stream (that's your "magic" file type marker), and will > also store the version (that's... well, version). RB replied Exactly and it seems to me that if all the help text points towards using the full power of serial in a CObject derived class why would the document derivative not be included since to me it is the base of the whole serialization process. Like if I have CMapStringToString's Runtime data and schema written to my file but I don't have my doc derivative's runtime data in the file unless I learn it from you on a news group, or my member data's schema unless I do what the help text says and put them in another CObject derived class with the full power of Serial macros. The whole thing just seems odd to me, unless for they were not wanting to tie the whole thing to the doc derivative's name as you previously pointed out, and if so why didn't they say so. See more on this lower down. > Goran wrote > In all honesty: I came up with this idea of my own and I don't know if > someone else does that. But I see no flaw in it. BTW, IIRC ;-)... If > there's an error in the file (e.g. it's really something else, not > your file), SerializeClass throws an exception with > CArchiveException::badClass. That gets nicely reported in document's > ReportStoreLoadException. RB replied Well actually about the same time you showed it to me I got out an old book I had bought used quite a while ago "MFC Programming by Alan Feuer" and I looked thru it and found the same idea (creating the doc derivative with the Serial macros ). But other than you and this one book, I have not seen it elsewhere searching on the net or other MFC books I have. >> RB previously wrote >> IMPLEMENT_SERIAL(CFileHandlingDoc, CDocument, 0) > Goran wrote >Wow, wow, not like that! You need SERIALIZABLE_SCHEMA in there. > I always start with SERIALIZABLE_SCHEMA|1, but I guess you can start > with 0 as well. RB replied Yes you showed me correct, I did the zero thing. Not much thought involved just figured I would start with zero since CMapStringToString does. Actually I have read about OR-ing the VERSIONABLE_SCHEMA define with the file schema, but I haven't yet gotten underneath the rhyme and reason of it. >> RB previously wrote >> if (ar.IsStoring()) >> { >> ar.SerializeClass(RUNTIME_CLASS(CFileHandlingDoc)); > Goran wrote > No, that goes in front of the "if". Otherwise, you're calling it twice > for no reason. RB replied Well yes you are correct. I did this because I had wanted to keep the order of Class runtime writes in order before their pertinant data writes. Of course obviously I could just skip this on the first object being written, but on all the other's CmStS etc, I would have to put them in both if else loops to keep the runtime data right with the actual object data (unless it was heap item and I used the ptr operator methods which does the WriteClass and the data write both together). >> Goran previously wrote >>Notes: >>* this ties serialization with your document class name, so you will >>have trouble changing it RB replied, well if I understand correctly what you meant with that statement, THIS would to me be a conceivable reason MFC designers did not include the Serial macro on the doc derivative. Because if you ever changed the name of you doc derivative in a future version you would never be able to read an old file back (with serialize anyhow) into a new version with a different doc class name. So maybe they thought it better to aim the help texts at a separate CObject derivative for SERIAL creation. That way if you changed the name of your app (slightly or otherwise) then the AppWizard generations would not break the doc derivative class's name tie to the older versions. >> Goran previously wrote >> (That might be a problem when/if a major overhaul of serialization >> occurs). RB replied Not quite sure exactly what you meant by a major overhaul of serialization. I am assuming you mean if I change my Doc derivatives name ? I know all of this has helped me learn more about the whole MFC structure so that is a plus. But at this point I kinda feel like "not" serializing the schema and class runtime "name" data of my doc derivative. In fact I think I would feel more comfortable going back with the MFC dyncreate creation and just writing out my doc data members to file first before any CObject derivatives that follow like CmStS or any others. That way I could just use my own schema system that is not tied to the doc derivative's name. As always I have learned a great deal from your replies. For a person wanting to learn, the newsgroup setup and people like you, Joe, Giovanni and all the other guys are a priceless help. RB
From: RB on 20 Jun 2010 20:01
Hey Joe thanks for replying > It does seem odd, but it also means that they are not assuming you require serialzation. > I'd be in the other fix, having to constantly get rid of DECLARE/IMPLEMENT_SERIAL > because I don't ever want to use the MFC serialization mechanism. > **** Well actually that is a very conceivable reason for not creating serial, so that makes two reasons so far. Since as Goran had pointed out to me serial ties the doc derivative class's name to the serialize schema. So I surmise that in future apps that had a slightly different name and doc derivative class name would break the Runtime class data match for a read from a newer version. That makes sense as to why the help texts always seem to point to making a separate CObject derivative for SERIAL creations. The thing that got me is why they did not be more clear about it and say it ? > In a sane worled, there would be SerializeIn(CArchive & ar) and SerializeOut(CArchive & > ar). And the stupid IsStoring method would not have to exist. > I think these are the same people who think that creating more files is evil. > **** Well as far as the mfc serialize scheme goes I can see that putting the storing and loading loops together helps keep the same order of writes and reads in my face so it might be visually less error prone. But I guess you could do that in your method also so that doesn't hold much water. But actually now I feel like I will use the dyncreate method and devise my own schema method for doc derivative members that need stored and keep the mfc serialize runtime class method for CmStS or any CObject derivatives I may need to create Serial. At least for the time being. As I get more experience under my belt I may forgo all of this ( like you) and just write my own persistence functions. >>const CRuntimeClass CFileHandlingDoc::classCFileHandlingDoc = >> { "CFileHandlingDoc", sizeof(class CFileHandlingDoc), >> 0x0000, // !RB replaced the 0xFFFF,! **************** > **** > Why? Just curious. > **** Nothing except having read the Laura said the framework supported serialize in the doc class without creating with Serial, I wanted to see if I could insert my schema of zero into the expanded dyncreate macro and then write and read it back. And I found that it did not work, so she must have been referring to some other aspect of framework support. It did write ok, I could see it in the dump. But it failed to read it back I presume since it did not have all of the serial macro capability to compare the written Class runtime data. |