http://www.developer.com/net/cplus/article.php/3355751/C-Tip-Uniquely-Identifying-Serialized-Files-with-Managed-C.htm
Welcome to this week's installment of .NET Tips & Techniques! Each week, award-winning Architect and Lead Programmer Tom Archer demonstrates how to perform a practical .NET programming task using either C# or Managed C++ Extensions. The technique I favor for uniquely identifying a serialized file is the rather obvious choice of a GUID (Globally Unique Identifier). The .NET System namespace even provides a structure (System::Guid) that provides overloaded operators for easy comparisons between Guid structures. The following basic steps demonstrate how to implement a Guid value as a unique file ID member into a C++ class:
The example code above presents two notable issues. First, while the SerializationInfo class provides several methods (GetString, GetBoolean, GetByte, and so forth) to read different types, it offers none for reading a Guid structure. Therefore, you'll need to read it as a String, construct a Guid object from that String, and then use the Guid structure's overloaded equality operator to compare the value. A second, less obvious, issue is that the exception being thrown will actually be caught by the .NET Formatter object doing the serialization. When the Formatter object catches the exception thrown from the constructor, it wraps that exception (as the inner exception) with its own exception object. You'll see how this comes into play shortly. In this latest article on .NET serialization using Managed C++, I covered using a GUID to uniquely identify your serialized files to ensure the integrity of your application. In the next article, I'll show you another extremely important issue with using serialization in a production environment—versioning. To download the accompanying source code for this tip, click here. The founder of the Archer Consulting Group (ACG), Tom Archer has been the project lead on three award-winning applications and is a best-selling author of 10 programming books as well as countless magazine and online articles.
C++ Tip: Uniquely Identifying Serialized Files with Managed C++
May 19, 2004
Defining a Guid Class Member to Identify Serialized Files
using namespace System::IO;
using namespace System::Runtime::Serialization;
using namespace System::Runtime::Serialization::Formatters
::Binary;
...
[Serializable]
__gc class YourClass : public ISerializable
{
public:
YourClass() {}
...
}
__gc class YourClass : public ISerializable
...
protected:
static Guid fileId = S"{FA054804-553A-4455-8CA0-
3A21167FE8A9}";
...
__gc class YourClass : public ISerializable
...
public:
void GetObjectData(SerializationInfo *si, StreamingContext sc)
{
si->AddValue(S"fileId", __box(this->fileId));
// Call AddValue for your other class members
}
(Note that the Guid member needs to be boxed via the __box keyword as it is a value type.)
__gc class YourClass : public ISerializable
...
protected:
YourClass(SerializationInfo *si, StreamingContext sc)
{
// Verify that the file is the correct format
String* tempFileId = si->GetString(S"fileId");
Guid tempGuid(tempFileId);
if (this->fileId != tempGuid)
{
throw new Exception(S"Invalid file type!");
}
// If we get this far, the file checks out. Read in other
// members
}
...
__gc class YourClassSerializer
{
public:
static YourClass* Open(String* fileName)
{
YourClass* yc = NULL;
FileStream* stream = new FileStream(fileName, FileMode::Open,
FileAccess::Read);
BinaryFormatter* formatter = new BinaryFormatter();
yc = static_cast<YourClass*>(formatter->Deserialize(stream));
stream->Close();
return yc;
}
static void Save(YourClass* yc, String* fileName)
{
FileStream* stream = new FileStream(fileName,
FileMode::Create,
FileAccess::Write);
BinaryFormatter* formatter = new BinaryFormatter();
formatter->Serialize(stream, yc);
stream->Close();
}
};
try
{
YourClass* yc;
// create and save test file
yc = new YourClass();
YourClassSerializer::Save(yc, S"test.yc");
// open existing file
// yc = static_cast<YourClass*>(YourClassSerializer::Open
// (S"test.yc"));
// save current file
// YourClassSerializer::Save(yc, S"test.yc");
}
catch(Exception* e)
{
Console::WriteLine(e->Message);
if (e->InnerException)
Console::WriteLine(e->InnerException->Message);
}
Uniquely Identify Your Serialized Files
Download the Code
About the Author