I am using BinaryFormatter to serialize and deserialize some objects. The structure of those object is as follows:
[Serializable()]
public class SerializableObject : ISerializable
{
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("SomeProperty", SomeProperty);
// similar for other properties
}
public SerializableObject(SerializationInfo info, StreamingContext context)
{
this.SomeProperty = (SomePropertyClass)info.GetValue("SomeProperty", typeof(SomePropertyClass));
// similar for other properties
}
}
I have noticed that when I try to deserialize an object, a TargetInvocation exception is thrown if the "SomeProperty" entry cannot be found (for example, because it was renamed or deleted). Since I intend to change the properties of SerializableObject class in future, I was thinking of catching the exception and setting the value of the problematic property to some default value instead of crashing my application, like this:
public SerializableObject(SerializationInfo info, StreamingContext context)
{
try
{
this.SomeProperty = (SomePropertyClass)info.GetValue("SomeProperty", typeof(SomePropertyClass));
}
catch (TargetInvocationException)
{
this.SomeProperty = SomePropertyClass.DefaultValue;
}
}
As we all know, catching exceptions that you don't know how or cannot handle is a bad practice, so I'm asking whether it's safe to catch it in this place? Can the same exception be thrown for any other reason (that I don't know and therefore shouldn't handle)?
Since TargetInvocationException
is not listed in the set of exceptions you should expect from that method (see MSDN) I would say it is wrong to try to handle that. A better approach is to loop on the names it does have, and pick the ones you expected:
foreach(SerializationEntry entry in info)
{
switch(entry.Name)
{
case "Foo": //...
case "Bar": //...
}
}
Or... use a less fussy serializer ;p
(btw, the above uses the alternative foreach
handling based on a typed enumerator and GetEnumerator()
method; it doesn't implement IEnumerable
/IEnumerable<T>
, but... it doesn't have to; you can use foreach
without that)