Serializing, add new member var problem.
-
I have a class that serializes itself out to a file using the SoapFormatter class. I have now added a new member variable to the class and want it to be serializeable too. But loading the previously saved file fails because this new member is not available in the saved file. If I set the new member to non-serializeable, the load works fine but then I can't save that member back out on the next save operation. Any ideas how to get around this problem without throwing my save file away and starting from scratch? Thanks! ~Steve
-
I have a class that serializes itself out to a file using the SoapFormatter class. I have now added a new member variable to the class and want it to be serializeable too. But loading the previously saved file fails because this new member is not available in the saved file. If I set the new member to non-serializeable, the load works fine but then I can't save that member back out on the next save operation. Any ideas how to get around this problem without throwing my save file away and starting from scratch? Thanks! ~Steve
Does your class implement the ISerializable interface? If so, you can override the ISerializable.GetObjectData method as well as the deserialization constructor to handle situations where the graph does not contain one or more fields that exist in the class. Note that the type still needs the [Serializable] attribute even when implementing ISerializable. Hope this helps.
The most exciting phrase to hear in science, the one that heralds the most discoveries, is not 'Eureka!' ('I found it!') but 'That's funny...’
-
I have a class that serializes itself out to a file using the SoapFormatter class. I have now added a new member variable to the class and want it to be serializeable too. But loading the previously saved file fails because this new member is not available in the saved file. If I set the new member to non-serializeable, the load works fine but then I can't save that member back out on the next save operation. Any ideas how to get around this problem without throwing my save file away and starting from scratch? Thanks! ~Steve
In addition to what the 'chimp said, there's actually a better way that is verion-independent. First, if you correctly version your assemblies (as you should, just don't use automatic versioning a la an asterisk in your
[assembly: AssemblyVersionAttribute]
) you'll have another problem: the serialized form won't deserialize into a newer version (the types don't match, because the versions are different). This is where aSerializationBinder
comes into play. You extend theSerializationBinder
and overrideBindToType
. This gives you a chance to "redirect" versions. What I typically do is take the assembly string (includes name, version, culture info, and public key token) and strip out everything but the version. I then concat the typename and left-over assembly name to get a version-independent type. When you then get theType
, the latest version of the assembly is loaded and the newType
is returned. This new version of your existing class would contain the new field (not "variable", which is declared within a method itself), so you may still have to use the 'chimp's suggestion of implementingISerializable
(typically a good idea when you want better control over serialization anyway). Below is a snippet of code showing what I mentioned:public class DiffVersionBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
string name = assembly.Name.Substring(0, assemblyName.IndexOf(','));
Type t = Type.GetType(typeName + ", " + name);
return t;
}
}To use:
IFormatter formatter = new SoapFormatter();
formatter.Binder = new DiffVersionBinder();
object obj = formatter.Deserialize(someStream);Microsoft MVP, Visual C# My Articles
-
Does your class implement the ISerializable interface? If so, you can override the ISerializable.GetObjectData method as well as the deserialization constructor to handle situations where the graph does not contain one or more fields that exist in the class. Note that the type still needs the [Serializable] attribute even when implementing ISerializable. Hope this helps.
The most exciting phrase to hear in science, the one that heralds the most discoveries, is not 'Eureka!' ('I found it!') but 'That's funny...’
Hey, sorry for not replying to say "thanks". I had found a solution shortly after I posted and then completely forgot that I posted! Thanks for the info... good stuff. ~Steve
-
In addition to what the 'chimp said, there's actually a better way that is verion-independent. First, if you correctly version your assemblies (as you should, just don't use automatic versioning a la an asterisk in your
[assembly: AssemblyVersionAttribute]
) you'll have another problem: the serialized form won't deserialize into a newer version (the types don't match, because the versions are different). This is where aSerializationBinder
comes into play. You extend theSerializationBinder
and overrideBindToType
. This gives you a chance to "redirect" versions. What I typically do is take the assembly string (includes name, version, culture info, and public key token) and strip out everything but the version. I then concat the typename and left-over assembly name to get a version-independent type. When you then get theType
, the latest version of the assembly is loaded and the newType
is returned. This new version of your existing class would contain the new field (not "variable", which is declared within a method itself), so you may still have to use the 'chimp's suggestion of implementingISerializable
(typically a good idea when you want better control over serialization anyway). Below is a snippet of code showing what I mentioned:public class DiffVersionBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
string name = assembly.Name.Substring(0, assemblyName.IndexOf(','));
Type t = Type.GetType(typeName + ", " + name);
return t;
}
}To use:
IFormatter formatter = new SoapFormatter();
formatter.Binder = new DiffVersionBinder();
object obj = formatter.Deserialize(someStream);Microsoft MVP, Visual C# My Articles
Hey, sorry for not replying to say "thanks". I had found a solution shortly after I posted and then completely forgot that I posted! Thanks for the info... good stuff. ~Steve