Наилучшим подходом было бы что-то вроде этого, это мой любимый подход:
public class SomeClass : ISerializable{
private float _fVersion;
....
public float Version {
get { return this._fVersion; }
}
private SomeClass(SerializationInfo info, StreamingContext context) {
bool bOk = false;
this._fVersion = info.GetSingle("versionID");
if (this._fVersion == 1.0F) bOk = this.HandleVersionOnePtZero(info, context);
if (this._fVersion == 1.1F) bOk = this.HandleVersionOnePtOne(info, context);
if (!bOk) throw new SerializationException(string.Format("SomeClass: Could not handle this version {0}.", this._fVersion.ToString()));
}
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("versionID", this._fVersion);
if (this._fVersion == 1.0F) {
info.AddValue("someField", ...);
info.AddValue("anotherField", ...);
}
if (this._fVersion == 1.1F) {
info.AddValue("someField1", ...);
info.AddValue("anotherField2", ...);
}
}
private bool HandleVersionOnePtZero(SerializationInfo info, StreamingContext context) {
bool rvOk = false;
... = info.GetValue("someField");
... = info.GetValue("anotherField");
}
private bool HandleVersionOnePtOne(SerializationInfo info, StreamingContext context) {
bool rvOk = false;
... = info.GetValue("someField1");
... = info.GetValue("anotherField2");
}
}
Вот так я применяю более жесткий контроль над сериализацией двоичных данных и увеличиваю версию. Теперь те из вас укажут, что уже есть возможность сделать это, но, начиная с .NET 1.1, старые привычки сильно умирают.
Обратите внимание, как в приведенном выше примере кода я использовал два разных метода HandleVersionOnePtZero
и HandleVersionOnePtOne
для обработки разных версий сериализованного потока. Делая это таким образом, я получаю большую степень гибкости, скажем, что если поле someField
нужно изменить? Также обратите внимание, что поле _fVersion
- это первое, что сначала делает сериализуемая подпрограмма, затем проверяет версию поля и решаете, какую из них использовать.
Единственное, что нужно сделать, это то, что если вы измените пространство имен, у вас возникнут трудности с десериализацией данных, но вы можете использовать класс SerializationBinder в качестве примера:
public class SomeClassBinder : System.Runtime.Serialization.SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
Type typeToDeserialize = null;
try {
// For each assemblyName/typeName that you want to deserialize to
// a different type, set typeToDeserialize to the desired type.
string assemVer1 = System.Reflection.Assembly.GetExecutingAssembly().FullName;
if (assemblyName.StartsWith("foobar")) {
assemblyName = assemVer1;
typeName = "fubar" + typeName.Substring(typeName.LastIndexOf("."), (typeName.Length - typeName.LastIndexOf(".")));
}
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
} catch (System.Exception ex1) {
throw ex1;
} finally {
}
return typeToDeserialize;
}
}
it would be called like this:
BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new SomeClassBinder();
SomeClass sc = bf.Deserialize(stream); // assume stream is declared and open
Надеюсь, это поможет