为什么SerializationInfo没有TryGetValue方法?

时间:2009-11-04 11:27:47

标签: c# serialization exception

在C#中实现ISerializable接口时,我们提供了一个构造函数,它接受SerializationInfo个对象,然后使用各种GetInt32GetObject等方法对其进行查询。为了填充我们试图反序列化的对象的字段。

实现此接口的一个主要原因,而不仅仅是使用[Serializable]属性,是为了向后兼容:如果我们在某个时刻向类中添加了新字段,我们可以捕获SerializationException由类的序列化旧版本抛出,并以适当的方式处理它们。

我的问题如下:为什么我们必须将这些例外用于控制流程?如果我反序列化大量前一段时间保存的类,可能每个类中的每个缺失字段都会抛出异常,从而导致性能非常差。

为什么SerializationInfo类不提供TryGetValue方法,如果名称字符串不存在,它们只会返回false

3 个答案:

答案 0 :(得分:25)

您可以迭代可用字段并使用switch,但是......

            foreach(SerializationEntry entry in info) {
                switch(entry.Name) {
                    ...
                }
            }

或者您可以使用protobuf-net ;-p

答案 1 :(得分:1)

除了枚举解决方案外,还有根据Reference Source的内部方法SerializationInfo.GetValueNoThrow()

您可以例如制作这样的扩展方法并避免异常开销:

static class SerializationInfoExtensions
{
    private static MethodInfo _GetValueNoThrow =
        typeof(SerializationInfo).GetMethod("GetValueNoThrow",
                                            BindingFlags.Instance | BindingFlags.NonPublic);

    public static Object GetOptValue(this SerializationInfo info, String name, Type type)
    {
        return _GetValueNoThrow.Invoke(info, new object[] { name, type });
    }
}

答案 2 :(得分:0)

没有人回答'为什么'但是我猜这是给了MS ..

我对任何有需要的人的实施:

public static class SerializationInfoExtensions
{
    public static bool TryGetValue<T>(this SerializationInfo serializationInfo, string name, out T value)
    {
        try
        {
            value = (T) serializationInfo.GetValue(name, typeof(T));
            return true;
        }
        catch (SerializationException)
        {
            value = default(T);
            return false;
        }
    }

    public static T GetValueOrDefault<T>(this SerializationInfo serializationInfo, string name, Lazy<T> defaultValue)
    {
        try
        {
            return (T) serializationInfo.GetValue(name, typeof(T));
        }
        catch (SerializationException)
        {
            return defaultValue.Value;
        }
    }
}