C # десериализация - безопасно ли перехватывать исключение TargetInvocationException? - PullRequest
2 голосов
/ 29 сентября 2011

Я использую BinaryFormatter для сериализации и десериализации некоторых объектов.Структура этих объектов выглядит следующим образом:

[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
    }
}

Я заметил, что при попытке десериализации объекта выдается исключение TargetInvocation, если запись «SomeProperty» не может быть найдена (например, потому что онабыл переименован или удален).Поскольку в будущем я намереваюсь изменить свойства класса SerializableObject, я думал о том, чтобы перехватить исключение и установить для значения проблемного свойства какое-то значение по умолчанию вместо сбоя приложения, например:

public SerializableObject(SerializationInfo info, StreamingContext context)
{
    try
    {
        this.SomeProperty = (SomePropertyClass)info.GetValue("SomeProperty", typeof(SomePropertyClass));
    }
    catch (TargetInvocationException)
    {
        this.SomeProperty = SomePropertyClass.DefaultValue;
    }
}

Как мы все знаем, ловить исключения, которые вы не знаете или не можете обработать, является плохой практикой, поэтому я спрашиваю, безопасно ли ловить их в этом месте?Может ли такое же исключение быть выдано по какой-либо другой причине (которую я не знаю и поэтому не должен обрабатывать)?

Ответы [ 2 ]

4 голосов
/ 29 сентября 2011

A TargetInvokationException должен иметь InnerException, который даст вам больше информации. Я бы посоветовал вам проверить внутреннее в блоке catch и перебросить, если ситуация просто отсутствует свойство.

2 голосов
/ 29 сентября 2011

Поскольку TargetInvocationException - это , а не , перечисленное в наборе исключений, которые вы должны ожидать от этого метода ( см. MSDN ), я бы сказал, что неправильно пытаться справиться с этим.Лучшим подходом является зацикливание имен, которые у есть , и выбор тех, которые вы ожидали:

    foreach(SerializationEntry entry in info)
    {
        switch(entry.Name)
        {
            case "Foo": //...   
            case "Bar": //...
        }
    }

или ... используйте менее суетливый сериализатор; p

(кстати, вышеупомянутый использует альтернативную обработку foreach, основанную на типизированном перечислителе и методе GetEnumerator(); он не реализует IEnumerable / IEnumerable<T>, но ... это не обязательно; выможно использовать foreach без этого)

...