Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rename MFC CArchive Serialized class

Tags:

c++

mfc

I'm using MFC's CArhive class to save off a project file for my app. One of the class names is wildly inaccurate and I'd like to change it, but simply changing the name everywhere renders previous archive files useless with an archive error. Is there a way to change the name of the archived class without rendering all previously saved files useless?

That is of course without using a typedef to access the existing class with a new name or keeping around a version of the class with the old name to read archived files and copying the read in objects to the same class with a new name.

like image 796
Jonathan Avatar asked Nov 05 '10 14:11

Jonathan


1 Answers

The crucial point is that when you use DECLARE_SERIAL and IMPLEMENT_SERIAL, a CRuntimeClass member is added to your class containing the name in its m_lpszClassName field. This CRuntimeClass object is also added to a list maintained by the framework that is searched when classes are dynamically created. You need to make sure that the CRuntimeClass object contains the old name of your class in m_lpszClassName.

The two options you have are:

  1. Override the construction of the CRuntimeClass object to set the name

  2. Change the class name stored in its m_lpszClassName field after it has been created

Overriding the construction of the CRuntimeClass object

To do this, you will need to make your own versions of DECLARE_DYMAMIC, DECLARE_DYNCREATE, DECLARE_SERIAL, IMPLEMENT_DYMAMIC, IMPLEMENT_DYNCREATE, and IMPLEMENT_SERIAL. You can just copy and rename the existing implementations. In your version of IMPLEMENT_DYNAMIC, you need to change the code that constructs the CRuntimeClass so that it is initialised with the old class's name.

Changing the class name stored in the m_lpszClassName field after the CRuntimeClass object has been created

As the CRuntimeClass is created by a static initializer, I don't think that you can do this from within your class. I think that the best place to do it is in your application's InitInstance. Add a static char* variable to your application's class containing the old class name. Then, in InitInstance, set the m_lpszClassName field in your class's CRuntimeClass.

  • The first method has the advantage of keeping changes within the class itself.
  • The second makes the application aware of the class in a way that it possibly shouldn't be.

Either way, the first thing to do is to completely familiarise yourself with the way dynamic creation and serialization work.

like image 184
Martin Broadhurst Avatar answered Sep 21 '22 16:09

Martin Broadhurst