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)

其他提示

A TargetInvokationException should have an InnerException which will give you more information. I'd suggest that you check the inner in the catch block and rethrow if the situation is simply a missing property.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top